[BACK]Return to aux.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mail

Annotation of src/usr.bin/mail/aux.c, Revision 1.26

1.26    ! okan        1: /*     $OpenBSD: aux.c,v 1.25 2009/10/27 23:59:40 deraadt Exp $        */
1.5       millert     2: /*     $NetBSD: aux.c,v 1.5 1997/05/13 06:15:52 mikel Exp $    */
1.2       deraadt     3:
1.1       deraadt     4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.21      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include "rcv.h"
                     34: #include "extern.h"
                     35:
                     36: /*
                     37:  * Mail -- a mail program
                     38:  *
                     39:  * Auxiliary functions.
                     40:  */
1.20      millert    41: static char *save2str(char *, char *);
1.1       deraadt    42:
                     43: /*
                     44:  * Return a pointer to a dynamic copy of the argument.
                     45:  */
                     46: char *
1.20      millert    47: savestr(char *str)
1.1       deraadt    48: {
                     49:        char *new;
                     50:        int size = strlen(str) + 1;
                     51:
1.7       millert    52:        if ((new = salloc(size)) != NULL)
1.6       millert    53:                (void)memcpy(new, str, size);
1.5       millert    54:        return(new);
1.1       deraadt    55: }
                     56:
                     57: /*
                     58:  * Make a copy of new argument incorporating old one.
                     59:  */
1.2       deraadt    60: static char *
1.20      millert    61: save2str(char *str, char *old)
1.1       deraadt    62: {
                     63:        char *new;
                     64:        int newsize = strlen(str) + 1;
                     65:        int oldsize = old ? strlen(old) + 1 : 0;
                     66:
1.7       millert    67:        if ((new = salloc(newsize + oldsize)) != NULL) {
1.1       deraadt    68:                if (oldsize) {
1.6       millert    69:                        (void)memcpy(new, old, oldsize);
1.1       deraadt    70:                        new[oldsize - 1] = ' ';
                     71:                }
1.6       millert    72:                (void)memcpy(new + oldsize, str, newsize);
1.1       deraadt    73:        }
1.5       millert    74:        return(new);
1.1       deraadt    75: }
                     76:
                     77: /*
                     78:  * Touch the named message by setting its MTOUCH flag.
                     79:  * Touched messages have the effect of not being sent
                     80:  * back to the system mailbox on exit.
                     81:  */
                     82: void
1.20      millert    83: touch(struct message *mp)
1.1       deraadt    84: {
                     85:
                     86:        mp->m_flag |= MTOUCH;
                     87:        if ((mp->m_flag & MREAD) == 0)
                     88:                mp->m_flag |= MREAD|MSTATUS;
                     89: }
                     90:
                     91: /*
                     92:  * Test to see if the passed file name is a directory.
                     93:  * Return true if it is.
                     94:  */
                     95: int
1.20      millert    96: isdir(char *name)
1.1       deraadt    97: {
                     98:        struct stat sbuf;
                     99:
                    100:        if (stat(name, &sbuf) < 0)
                    101:                return(0);
1.16      millert   102:        return(S_ISDIR(sbuf.st_mode));
1.1       deraadt   103: }
                    104:
                    105: /*
                    106:  * Count the number of arguments in the given string raw list.
                    107:  */
                    108: int
1.20      millert   109: argcount(char **argv)
1.1       deraadt   110: {
1.13      millert   111:        char **ap;
1.1       deraadt   112:
1.7       millert   113:        for (ap = argv; *ap++ != NULL;)
1.1       deraadt   114:                ;
1.5       millert   115:        return(ap - argv - 1);
1.1       deraadt   116: }
                    117:
                    118: /*
                    119:  * Return the desired header line from the passed message
1.7       millert   120:  * pointer (or NULL if the desired header field is not available).
1.1       deraadt   121:  */
                    122: char *
1.20      millert   123: hfield(char *field, struct message *mp)
1.1       deraadt   124: {
1.13      millert   125:        FILE *ibuf;
1.1       deraadt   126:        char linebuf[LINESIZE];
1.13      millert   127:        int lc;
                    128:        char *hfield;
1.7       millert   129:        char *colon, *oldhfield = NULL;
1.1       deraadt   130:
                    131:        ibuf = setinput(mp);
                    132:        if ((lc = mp->m_lines - 1) < 0)
1.7       millert   133:                return(NULL);
1.19      millert   134:        if (readline(ibuf, linebuf, LINESIZE, NULL) < 0)
1.7       millert   135:                return(NULL);
1.1       deraadt   136:        while (lc > 0) {
                    137:                if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
1.5       millert   138:                        return(oldhfield);
1.2       deraadt   139:                if ((hfield = ishfield(linebuf, colon, field)) != NULL)
1.1       deraadt   140:                        oldhfield = save2str(hfield, oldhfield);
                    141:        }
1.5       millert   142:        return(oldhfield);
1.1       deraadt   143: }
                    144:
                    145: /*
                    146:  * Return the next header field found in the given message.
                    147:  * Return >= 0 if something found, < 0 elsewise.
                    148:  * "colon" is set to point to the colon in the header.
                    149:  * Must deal with \ continuations & other such fraud.
                    150:  */
                    151: int
1.20      millert   152: gethfield(FILE *f, char *linebuf, int rem, char **colon)
1.1       deraadt   153: {
                    154:        char line2[LINESIZE];
1.13      millert   155:        char *cp, *cp2;
                    156:        int c;
1.1       deraadt   157:
                    158:        for (;;) {
                    159:                if (--rem < 0)
1.5       millert   160:                        return(-1);
1.19      millert   161:                if ((c = readline(f, linebuf, LINESIZE, NULL)) <= 0)
1.5       millert   162:                        return(-1);
1.26    ! okan      163:                for (cp = linebuf;
        !           164:                    isprint((unsigned char)*cp) && *cp != ' ' && *cp != ':';
        !           165:                    cp++)
1.1       deraadt   166:                        ;
                    167:                if (*cp != ':' || cp == linebuf)
                    168:                        continue;
                    169:                /*
                    170:                 * I guess we got a headline.
                    171:                 * Handle wraparounding
                    172:                 */
                    173:                *colon = cp;
                    174:                cp = linebuf + c;
                    175:                for (;;) {
                    176:                        while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
                    177:                                ;
                    178:                        cp++;
                    179:                        if (rem <= 0)
                    180:                                break;
                    181:                        ungetc(c = getc(f), f);
                    182:                        if (c != ' ' && c != '\t')
                    183:                                break;
1.19      millert   184:                        if ((c = readline(f, line2, LINESIZE, NULL)) < 0)
1.1       deraadt   185:                                break;
                    186:                        rem--;
                    187:                        for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
                    188:                                ;
                    189:                        c -= cp2 - line2;
                    190:                        if (cp + c >= linebuf + LINESIZE - 2)
                    191:                                break;
                    192:                        *cp++ = ' ';
1.6       millert   193:                        (void)memcpy(cp, cp2, c);
1.1       deraadt   194:                        cp += c;
                    195:                }
                    196:                *cp = 0;
1.5       millert   197:                return(rem);
1.1       deraadt   198:        }
                    199:        /* NOTREACHED */
                    200: }
                    201:
                    202: /*
                    203:  * Check whether the passed line is a header line of
                    204:  * the desired breed.  Return the field body, or 0.
                    205:  */
                    206:
                    207: char*
1.20      millert   208: ishfield(char *linebuf, char *colon, char *field)
1.1       deraadt   209: {
1.13      millert   210:        char *cp = colon;
1.1       deraadt   211:
                    212:        *cp = 0;
                    213:        if (strcasecmp(linebuf, field) != 0) {
                    214:                *cp = ':';
1.5       millert   215:                return(0);
1.1       deraadt   216:        }
                    217:        *cp = ':';
                    218:        for (cp++; *cp == ' ' || *cp == '\t'; cp++)
                    219:                ;
1.5       millert   220:        return(cp);
1.1       deraadt   221: }
                    222:
                    223: /*
1.10      millert   224:  * Copy a string, lowercasing it as we go.  ``dsize'' should be
1.20      millert   225:  * the real size (not len) of the dest string (guarantee NUL term).
1.1       deraadt   226:  */
1.20      millert   227: size_t
                    228: istrlcpy(char *dst, const char *src, size_t dsize)
1.1       deraadt   229: {
1.20      millert   230:        char *d = dst;
                    231:        const char *s = src;
                    232:        size_t n = dsize;
                    233:
                    234:        /* Copy as many bytes as will fit */
                    235:        if (n != 0 && --n != 0) {
                    236:                do {
1.26    ! okan      237:                        if ((*d++ = tolower((unsigned char)*s++)) == 0)
1.20      millert   238:                                break;
                    239:                } while (--n != 0);
                    240:        }
1.1       deraadt   241:
1.20      millert   242:        /* Not enough room in dst, add NUL and traverse rest of src */
                    243:        if (n == 0) {
                    244:                if (dsize != 0)
                    245:                        *d = '\0';              /* NUL-terminate dst */
                    246:                while (*s++)
                    247:                        ;
1.10      millert   248:        }
1.20      millert   249:
                    250:        return(s - src - 1);    /* count does not include NUL */
1.1       deraadt   251: }
                    252:
                    253: /*
                    254:  * The following code deals with input stacking to do source
                    255:  * commands.  All but the current file pointer are saved on
                    256:  * the stack.
                    257:  */
                    258: static int     ssp;                    /* Top of file stack */
                    259: struct sstack {
                    260:        FILE    *s_file;                /* File we were in. */
                    261:        int     s_cond;                 /* Saved state of conditionals */
                    262:        int     s_loading;              /* Loading .mailrc, etc. */
                    263: } sstack[NOFILE];
                    264:
                    265: /*
                    266:  * Pushdown current input file and switch to a new one.
                    267:  * Set the global flag "sourcing" so that others will realize
                    268:  * that they are no longer reading from a tty (in all probability).
                    269:  */
                    270: int
1.20      millert   271: source(void *v)
1.1       deraadt   272: {
1.2       deraadt   273:        char **arglist = v;
1.1       deraadt   274:        FILE *fi;
                    275:        char *cp;
                    276:
1.7       millert   277:        if ((cp = expand(*arglist)) == NULL)
1.1       deraadt   278:                return(1);
                    279:        if ((fi = Fopen(cp, "r")) == NULL) {
1.15      millert   280:                warn("%s", cp);
1.1       deraadt   281:                return(1);
                    282:        }
                    283:        if (ssp >= NOFILE - 1) {
1.5       millert   284:                puts("Too much \"sourcing\" going on.");
                    285:                (void)Fclose(fi);
1.1       deraadt   286:                return(1);
                    287:        }
                    288:        sstack[ssp].s_file = input;
                    289:        sstack[ssp].s_cond = cond;
                    290:        sstack[ssp].s_loading = loading;
                    291:        ssp++;
                    292:        loading = 0;
                    293:        cond = CANY;
                    294:        input = fi;
                    295:        sourcing++;
                    296:        return(0);
                    297: }
                    298:
                    299: /*
                    300:  * Pop the current input back to the previous level.
                    301:  * Update the "sourcing" flag as appropriate.
                    302:  */
                    303: int
1.20      millert   304: unstack(void)
1.1       deraadt   305: {
1.20      millert   306:
1.1       deraadt   307:        if (ssp <= 0) {
1.5       millert   308:                puts("\"Source\" stack over-pop.");
1.1       deraadt   309:                sourcing = 0;
                    310:                return(1);
                    311:        }
1.5       millert   312:        (void)Fclose(input);
1.1       deraadt   313:        if (cond != CANY)
1.5       millert   314:                puts("Unmatched \"if\"");
1.1       deraadt   315:        ssp--;
                    316:        cond = sstack[ssp].s_cond;
                    317:        loading = sstack[ssp].s_loading;
                    318:        input = sstack[ssp].s_file;
                    319:        if (ssp == 0)
                    320:                sourcing = loading;
                    321:        return(0);
                    322: }
                    323:
                    324: /*
                    325:  * Touch the indicated file.
                    326:  * This is nifty for the shell.
                    327:  */
                    328: void
1.20      millert   329: alter(char *name)
1.1       deraadt   330: {
                    331:        struct stat sb;
                    332:        struct timeval tv[2];
                    333:
                    334:        if (stat(name, &sb))
                    335:                return;
1.13      millert   336:        (void) gettimeofday(&tv[0], (struct timezone *)0);
                    337:        tv[0].tv_sec++;
1.16      millert   338: #ifdef TIMESPEC_TO_TIMEVAL
1.13      millert   339:        TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec);
1.16      millert   340: #else
                    341:        tv[1].tv_sec = sb.st_mtime;
                    342: #endif
1.1       deraadt   343:        (void)utimes(name, tv);
                    344: }
                    345:
                    346: /*
                    347:  * Examine the passed line buffer and
                    348:  * return true if it is all blanks and tabs.
                    349:  */
                    350: int
1.20      millert   351: blankline(char *linebuf)
1.1       deraadt   352: {
1.13      millert   353:        char *cp;
1.1       deraadt   354:
                    355:        for (cp = linebuf; *cp; cp++)
                    356:                if (*cp != ' ' && *cp != '\t')
                    357:                        return(0);
                    358:        return(1);
                    359: }
                    360:
                    361: /*
                    362:  * Get sender's name from this message.  If the message has
                    363:  * a bunch of arpanet stuff in it, we may have to skin the name
                    364:  * before returning it.
                    365:  */
                    366: char *
1.20      millert   367: nameof(struct message *mp, int reptype)
1.1       deraadt   368: {
1.13      millert   369:        char *cp, *cp2;
1.1       deraadt   370:
                    371:        cp = skin(name1(mp, reptype));
                    372:        if (reptype != 0 || charcount(cp, '!') < 2)
                    373:                return(cp);
1.3       millert   374:        cp2 = strrchr(cp, '!');
1.1       deraadt   375:        cp2--;
                    376:        while (cp2 > cp && *cp2 != '!')
                    377:                cp2--;
                    378:        if (*cp2 == '!')
                    379:                return(cp2 + 1);
                    380:        return(cp);
                    381: }
                    382:
                    383: /*
                    384:  * Start of a "comment".
                    385:  * Ignore it.
                    386:  */
                    387: char *
1.20      millert   388: skip_comment(char *cp)
1.1       deraadt   389: {
1.13      millert   390:        int nesting = 1;
1.1       deraadt   391:
                    392:        for (; nesting > 0 && *cp; cp++) {
                    393:                switch (*cp) {
                    394:                case '\\':
                    395:                        if (cp[1])
                    396:                                cp++;
                    397:                        break;
                    398:                case '(':
                    399:                        nesting++;
                    400:                        break;
                    401:                case ')':
                    402:                        nesting--;
                    403:                        break;
                    404:                }
                    405:        }
1.5       millert   406:        return(cp);
1.1       deraadt   407: }
                    408:
                    409: /*
                    410:  * Skin an arpa net address according to the RFC 822 interpretation
                    411:  * of "host-phrase."
                    412:  */
                    413: char *
1.20      millert   414: skin(char *name)
1.1       deraadt   415: {
1.13      millert   416:        char *nbuf, *bufend, *cp, *cp2;
                    417:        int c, gotlt, lastsp;
1.1       deraadt   418:
1.7       millert   419:        if (name == NULL)
                    420:                return(NULL);
                    421:        if (strchr(name, '(') == NULL && strchr(name, '<') == NULL
                    422:            && strchr(name, ' ') == NULL)
1.1       deraadt   423:                return(name);
1.11      millert   424:
                    425:        /* We assume that length(input) <= length(output) */
1.12      millert   426:        if ((nbuf = (char *)malloc(strlen(name) + 1)) == NULL)
1.13      millert   427:                errx(1, "Out of memory");
1.1       deraadt   428:        gotlt = 0;
                    429:        lastsp = 0;
1.12      millert   430:        bufend = nbuf;
1.26    ! okan      431:        for (cp = name, cp2 = bufend; (c = (unsigned char)*cp++) != '\0'; ) {
1.1       deraadt   432:                switch (c) {
                    433:                case '(':
                    434:                        cp = skip_comment(cp);
                    435:                        lastsp = 0;
                    436:                        break;
                    437:
                    438:                case '"':
                    439:                        /*
                    440:                         * Start of a "quoted-string".
                    441:                         * Copy it in its entirety.
                    442:                         */
1.26    ! okan      443:                        while ((c = (unsigned char)*cp) != '\0') {
1.1       deraadt   444:                                cp++;
                    445:                                if (c == '"')
                    446:                                        break;
                    447:                                if (c != '\\')
                    448:                                        *cp2++ = c;
1.26    ! okan      449:                                else if ((c = (unsigned char)*cp) != '\0') {
1.1       deraadt   450:                                        *cp2++ = c;
                    451:                                        cp++;
                    452:                                }
                    453:                        }
                    454:                        lastsp = 0;
                    455:                        break;
                    456:
                    457:                case ' ':
1.24      martynas  458:                        if (strncmp(cp, "at ", 3) == 0)
1.1       deraadt   459:                                cp += 3, *cp2++ = '@';
                    460:                        else
1.24      martynas  461:                        if (strncmp(cp, "@ ", 2) == 0)
1.1       deraadt   462:                                cp += 2, *cp2++ = '@';
                    463:                        else
                    464:                                lastsp = 1;
                    465:                        break;
                    466:
                    467:                case '<':
                    468:                        cp2 = bufend;
                    469:                        gotlt++;
                    470:                        lastsp = 0;
                    471:                        break;
                    472:
                    473:                case '>':
                    474:                        if (gotlt) {
                    475:                                gotlt = 0;
1.26    ! okan      476:                                while ((c = (unsigned char)*cp) && c != ',') {
1.1       deraadt   477:                                        cp++;
                    478:                                        if (c == '(')
                    479:                                                cp = skip_comment(cp);
                    480:                                        else if (c == '"')
1.26    ! okan      481:                                                while ((c = (unsigned char)*cp) != '\0') {
1.1       deraadt   482:                                                        cp++;
                    483:                                                        if (c == '"')
                    484:                                                                break;
                    485:                                                        if (c == '\\' && *cp)
                    486:                                                                cp++;
                    487:                                                }
                    488:                                }
                    489:                                lastsp = 0;
                    490:                                break;
                    491:                        }
                    492:                        /* Fall into . . . */
                    493:
                    494:                default:
                    495:                        if (lastsp) {
                    496:                                lastsp = 0;
                    497:                                *cp2++ = ' ';
                    498:                        }
                    499:                        *cp2++ = c;
1.17      millert   500:                        if (c == ',' && *cp == ' ' && !gotlt) {
1.1       deraadt   501:                                *cp2++ = ' ';
1.18      millert   502:                                while (*++cp == ' ')
1.1       deraadt   503:                                        ;
                    504:                                lastsp = 0;
                    505:                                bufend = cp2;
                    506:                        }
                    507:                }
                    508:        }
                    509:        *cp2 = 0;
                    510:
1.17      millert   511:        if ((cp = (char *)realloc(nbuf, strlen(nbuf) + 1)) != NULL)
                    512:                nbuf = cp;
1.12      millert   513:        return(nbuf);
1.1       deraadt   514: }
                    515:
                    516: /*
                    517:  * Fetch the sender's name from the passed message.
                    518:  * Reptype can be
                    519:  *     0 -- get sender's name for display purposes
                    520:  *     1 -- get sender's name for reply
                    521:  *     2 -- get sender's name for Reply
                    522:  */
                    523: char *
1.20      millert   524: name1(struct message *mp, int reptype)
1.1       deraadt   525: {
                    526:        char namebuf[LINESIZE];
                    527:        char linebuf[LINESIZE];
1.13      millert   528:        char *cp, *cp2;
                    529:        FILE *ibuf;
1.1       deraadt   530:        int first = 1;
                    531:
1.7       millert   532:        if ((cp = hfield("from", mp)) != NULL)
1.5       millert   533:                return(cp);
1.7       millert   534:        if (reptype == 0 && (cp = hfield("sender", mp)) != NULL)
1.5       millert   535:                return(cp);
1.1       deraadt   536:        ibuf = setinput(mp);
1.4       deraadt   537:        namebuf[0] = '\0';
1.19      millert   538:        if (readline(ibuf, linebuf, LINESIZE, NULL) < 0)
1.1       deraadt   539:                return(savestr(namebuf));
                    540: newname:
                    541:        for (cp = linebuf; *cp && *cp != ' '; cp++)
                    542:                ;
                    543:        for (; *cp == ' ' || *cp == '\t'; cp++)
                    544:                ;
                    545:        for (cp2 = &namebuf[strlen(namebuf)];
                    546:             *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;)
                    547:                *cp2++ = *cp++;
                    548:        *cp2 = '\0';
1.19      millert   549:        if (readline(ibuf, linebuf, LINESIZE, NULL) < 0)
1.1       deraadt   550:                return(savestr(namebuf));
1.3       millert   551:        if ((cp = strchr(linebuf, 'F')) == NULL)
1.1       deraadt   552:                return(savestr(namebuf));
                    553:        if (strncmp(cp, "From", 4) != 0)
                    554:                return(savestr(namebuf));
1.3       millert   555:        while ((cp = strchr(cp, 'r')) != NULL) {
1.1       deraadt   556:                if (strncmp(cp, "remote", 6) == 0) {
1.3       millert   557:                        if ((cp = strchr(cp, 'f')) == NULL)
1.1       deraadt   558:                                break;
                    559:                        if (strncmp(cp, "from", 4) != 0)
                    560:                                break;
1.3       millert   561:                        if ((cp = strchr(cp, ' ')) == NULL)
1.1       deraadt   562:                                break;
                    563:                        cp++;
                    564:                        if (first) {
1.5       millert   565:                                cp2 = namebuf;
1.1       deraadt   566:                                first = 0;
                    567:                        } else
1.5       millert   568:                                cp2 = strrchr(namebuf, '!') + 1;
1.20      millert   569:                        strlcpy(cp2, cp, sizeof(namebuf) - (cp2 - namebuf) - 1);
                    570:                        strlcat(namebuf, "!", sizeof(namebuf));
1.1       deraadt   571:                        goto newname;
                    572:                }
                    573:                cp++;
                    574:        }
                    575:        return(savestr(namebuf));
                    576: }
                    577:
                    578: /*
                    579:  * Count the occurances of c in str
                    580:  */
                    581: int
1.20      millert   582: charcount(char *str, int c)
1.1       deraadt   583: {
1.13      millert   584:        char *cp;
                    585:        int i;
1.1       deraadt   586:
                    587:        for (i = 0, cp = str; *cp; cp++)
                    588:                if (*cp == c)
                    589:                        i++;
                    590:        return(i);
                    591: }
                    592:
                    593: /*
                    594:  * Copy s1 to s2, return pointer to null in s2.
                    595:  */
                    596: char *
1.20      millert   597: copy(char *s1, char *s2)
1.1       deraadt   598: {
                    599:
1.2       deraadt   600:        while ((*s2++ = *s1++) != '\0')
1.1       deraadt   601:                ;
1.5       millert   602:        return(s2 - 1);
1.1       deraadt   603: }
                    604:
                    605: /*
                    606:  * See if the given header field is supposed to be ignored.
                    607:  */
                    608: int
1.20      millert   609: isign(char *field, struct ignoretab ignore[2])
1.1       deraadt   610: {
1.5       millert   611:        char realfld[LINESIZE];
1.1       deraadt   612:
                    613:        if (ignore == ignoreall)
1.5       millert   614:                return(1);
1.1       deraadt   615:        /*
                    616:         * Lower-case the string, so that "Status" and "status"
                    617:         * will hash to the same place.
                    618:         */
1.20      millert   619:        istrlcpy(realfld, field, sizeof(realfld));
1.1       deraadt   620:        if (ignore[1].i_count > 0)
1.5       millert   621:                return(!member(realfld, ignore + 1));
1.1       deraadt   622:        else
1.5       millert   623:                return(member(realfld, ignore));
1.1       deraadt   624: }
                    625:
                    626: int
1.20      millert   627: member(char *realfield, struct ignoretab *table)
1.1       deraadt   628: {
1.13      millert   629:        struct ignore *igp;
1.1       deraadt   630:
                    631:        for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link)
                    632:                if (*igp->i_field == *realfield &&
                    633:                    equal(igp->i_field, realfield))
1.5       millert   634:                        return(1);
                    635:        return(0);
1.14      millert   636: }
                    637:
                    638: void
1.20      millert   639: clearnew(void)
1.14      millert   640: {
                    641:        struct message *mp;
                    642:
                    643:        for (mp = &message[0]; mp < &message[msgCount]; mp++) {
                    644:                if (mp->m_flag & MNEW) {
                    645:                        mp->m_flag &= ~MNEW;
                    646:                        mp->m_flag |= MSTATUS;
                    647:                }
                    648:        }
1.1       deraadt   649: }