[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.18

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