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

1.6     ! millert     1: /*     $OpenBSD: aux.c,v 1.5 1997/07/13 21:21:08 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.6     ! millert    41: static char rcsid[] = "$OpenBSD: aux.c,v 1.5 1997/07/13 21:21:08 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:
                     65:        if ((new = salloc(size)) != NOSTR)
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:
                     81:        if ((new = salloc(newsize + oldsize)) != NOSTR) {
                     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:  * Announce a fatal error and die.
                     93:  */
                     94: #if __STDC__
                     95: #include <stdarg.h>
                     96: #else
                     97: #include <varargs.h>
                     98: #endif
                     99:
                    100: void
                    101: #if __STDC__
                    102: panic(const char *fmt, ...)
                    103: #else
                    104: panic(fmt, va_alist)
                    105:        char *fmt;
                    106:         va_dcl
                    107: #endif
                    108: {
                    109:        va_list ap;
                    110: #if __STDC__
                    111:        va_start(ap, fmt);
                    112: #else
                    113:        va_start(ap);
                    114: #endif
                    115:        (void)fprintf(stderr, "panic: ");
                    116:        vfprintf(stderr, fmt, ap);
                    117:        va_end(ap);
1.5       millert   118:        (void)putc('\n', stderr);
1.1       deraadt   119:        fflush(stderr);
                    120:        abort();
                    121: }
                    122:
                    123: /*
                    124:  * Touch the named message by setting its MTOUCH flag.
                    125:  * Touched messages have the effect of not being sent
                    126:  * back to the system mailbox on exit.
                    127:  */
                    128: void
                    129: touch(mp)
                    130:        register struct message *mp;
                    131: {
                    132:
                    133:        mp->m_flag |= MTOUCH;
                    134:        if ((mp->m_flag & MREAD) == 0)
                    135:                mp->m_flag |= MREAD|MSTATUS;
                    136: }
                    137:
                    138: /*
                    139:  * Test to see if the passed file name is a directory.
                    140:  * Return true if it is.
                    141:  */
                    142: int
                    143: isdir(name)
                    144:        char name[];
                    145: {
                    146:        struct stat sbuf;
                    147:
                    148:        if (stat(name, &sbuf) < 0)
                    149:                return(0);
                    150:        return((sbuf.st_mode & S_IFMT) == S_IFDIR);
                    151: }
                    152:
                    153: /*
                    154:  * Count the number of arguments in the given string raw list.
                    155:  */
                    156: int
                    157: argcount(argv)
                    158:        char **argv;
                    159: {
                    160:        register char **ap;
                    161:
                    162:        for (ap = argv; *ap++ != NOSTR;)
                    163:                ;
1.5       millert   164:        return(ap - argv - 1);
1.1       deraadt   165: }
                    166:
                    167: /*
                    168:  * Return the desired header line from the passed message
                    169:  * pointer (or NOSTR if the desired header field is not available).
                    170:  */
                    171: char *
                    172: hfield(field, mp)
                    173:        char field[];
                    174:        struct message *mp;
                    175: {
                    176:        register FILE *ibuf;
                    177:        char linebuf[LINESIZE];
                    178:        register int lc;
                    179:        register char *hfield;
                    180:        char *colon, *oldhfield = NOSTR;
                    181:
                    182:        ibuf = setinput(mp);
                    183:        if ((lc = mp->m_lines - 1) < 0)
1.5       millert   184:                return(NOSTR);
1.1       deraadt   185:        if (readline(ibuf, linebuf, LINESIZE) < 0)
1.5       millert   186:                return(NOSTR);
1.1       deraadt   187:        while (lc > 0) {
                    188:                if ((lc = gethfield(ibuf, linebuf, lc, &colon)) < 0)
1.5       millert   189:                        return(oldhfield);
1.2       deraadt   190:                if ((hfield = ishfield(linebuf, colon, field)) != NULL)
1.1       deraadt   191:                        oldhfield = save2str(hfield, oldhfield);
                    192:        }
1.5       millert   193:        return(oldhfield);
1.1       deraadt   194: }
                    195:
                    196: /*
                    197:  * Return the next header field found in the given message.
                    198:  * Return >= 0 if something found, < 0 elsewise.
                    199:  * "colon" is set to point to the colon in the header.
                    200:  * Must deal with \ continuations & other such fraud.
                    201:  */
                    202: int
                    203: gethfield(f, linebuf, rem, colon)
                    204:        register FILE *f;
                    205:        char linebuf[];
                    206:        register int rem;
                    207:        char **colon;
                    208: {
                    209:        char line2[LINESIZE];
                    210:        register char *cp, *cp2;
                    211:        register int c;
                    212:
                    213:        for (;;) {
                    214:                if (--rem < 0)
1.5       millert   215:                        return(-1);
1.1       deraadt   216:                if ((c = readline(f, linebuf, LINESIZE)) <= 0)
1.5       millert   217:                        return(-1);
1.1       deraadt   218:                for (cp = linebuf; isprint(*cp) && *cp != ' ' && *cp != ':';
                    219:                     cp++)
                    220:                        ;
                    221:                if (*cp != ':' || cp == linebuf)
                    222:                        continue;
                    223:                /*
                    224:                 * I guess we got a headline.
                    225:                 * Handle wraparounding
                    226:                 */
                    227:                *colon = cp;
                    228:                cp = linebuf + c;
                    229:                for (;;) {
                    230:                        while (--cp >= linebuf && (*cp == ' ' || *cp == '\t'))
                    231:                                ;
                    232:                        cp++;
                    233:                        if (rem <= 0)
                    234:                                break;
                    235:                        ungetc(c = getc(f), f);
                    236:                        if (c != ' ' && c != '\t')
                    237:                                break;
                    238:                        if ((c = readline(f, line2, LINESIZE)) < 0)
                    239:                                break;
                    240:                        rem--;
                    241:                        for (cp2 = line2; *cp2 == ' ' || *cp2 == '\t'; cp2++)
                    242:                                ;
                    243:                        c -= cp2 - line2;
                    244:                        if (cp + c >= linebuf + LINESIZE - 2)
                    245:                                break;
                    246:                        *cp++ = ' ';
1.6     ! millert   247:                        (void)memcpy(cp, cp2, c);
1.1       deraadt   248:                        cp += c;
                    249:                }
                    250:                *cp = 0;
1.5       millert   251:                return(rem);
1.1       deraadt   252:        }
                    253:        /* NOTREACHED */
                    254: }
                    255:
                    256: /*
                    257:  * Check whether the passed line is a header line of
                    258:  * the desired breed.  Return the field body, or 0.
                    259:  */
                    260:
                    261: char*
                    262: ishfield(linebuf, colon, field)
                    263:        char linebuf[], field[];
                    264:        char *colon;
                    265: {
                    266:        register char *cp = colon;
                    267:
                    268:        *cp = 0;
                    269:        if (strcasecmp(linebuf, field) != 0) {
                    270:                *cp = ':';
1.5       millert   271:                return(0);
1.1       deraadt   272:        }
                    273:        *cp = ':';
                    274:        for (cp++; *cp == ' ' || *cp == '\t'; cp++)
                    275:                ;
1.5       millert   276:        return(cp);
1.1       deraadt   277: }
                    278:
                    279: /*
                    280:  * Copy a string, lowercasing it as we go.
                    281:  */
                    282: void
                    283: istrcpy(dest, src)
                    284:        register char *dest, *src;
                    285: {
                    286:
                    287:        do {
                    288:                if (isupper(*src))
                    289:                        *dest++ = tolower(*src);
                    290:                else
                    291:                        *dest++ = *src;
                    292:        } while (*src++ != 0);
                    293: }
                    294:
                    295: /*
                    296:  * The following code deals with input stacking to do source
                    297:  * commands.  All but the current file pointer are saved on
                    298:  * the stack.
                    299:  */
                    300:
                    301: static int     ssp;                    /* Top of file stack */
                    302: struct sstack {
                    303:        FILE    *s_file;                /* File we were in. */
                    304:        int     s_cond;                 /* Saved state of conditionals */
                    305:        int     s_loading;              /* Loading .mailrc, etc. */
                    306: } sstack[NOFILE];
                    307:
                    308: /*
                    309:  * Pushdown current input file and switch to a new one.
                    310:  * Set the global flag "sourcing" so that others will realize
                    311:  * that they are no longer reading from a tty (in all probability).
                    312:  */
                    313: int
1.2       deraadt   314: source(v)
                    315:        void *v;
1.1       deraadt   316: {
1.2       deraadt   317:        char **arglist = v;
1.1       deraadt   318:        FILE *fi;
                    319:        char *cp;
                    320:
                    321:        if ((cp = expand(*arglist)) == NOSTR)
                    322:                return(1);
                    323:        if ((fi = Fopen(cp, "r")) == NULL) {
1.5       millert   324:                warn(cp);
1.1       deraadt   325:                return(1);
                    326:        }
                    327:        if (ssp >= NOFILE - 1) {
1.5       millert   328:                puts("Too much \"sourcing\" going on.");
                    329:                (void)Fclose(fi);
1.1       deraadt   330:                return(1);
                    331:        }
                    332:        sstack[ssp].s_file = input;
                    333:        sstack[ssp].s_cond = cond;
                    334:        sstack[ssp].s_loading = loading;
                    335:        ssp++;
                    336:        loading = 0;
                    337:        cond = CANY;
                    338:        input = fi;
                    339:        sourcing++;
                    340:        return(0);
                    341: }
                    342:
                    343: /*
                    344:  * Pop the current input back to the previous level.
                    345:  * Update the "sourcing" flag as appropriate.
                    346:  */
                    347: int
                    348: unstack()
                    349: {
                    350:        if (ssp <= 0) {
1.5       millert   351:                puts("\"Source\" stack over-pop.");
1.1       deraadt   352:                sourcing = 0;
                    353:                return(1);
                    354:        }
1.5       millert   355:        (void)Fclose(input);
1.1       deraadt   356:        if (cond != CANY)
1.5       millert   357:                puts("Unmatched \"if\"");
1.1       deraadt   358:        ssp--;
                    359:        cond = sstack[ssp].s_cond;
                    360:        loading = sstack[ssp].s_loading;
                    361:        input = sstack[ssp].s_file;
                    362:        if (ssp == 0)
                    363:                sourcing = loading;
                    364:        return(0);
                    365: }
                    366:
                    367: /*
                    368:  * Touch the indicated file.
                    369:  * This is nifty for the shell.
                    370:  */
                    371: void
                    372: alter(name)
                    373:        char *name;
                    374: {
                    375:        struct stat sb;
                    376:        struct timeval tv[2];
                    377:
                    378:        if (stat(name, &sb))
                    379:                return;
                    380:        tv[0].tv_sec = time((time_t *)0) + 1;
                    381:        tv[1].tv_sec = sb.st_mtime;
                    382:        tv[0].tv_usec = tv[1].tv_usec = 0;
                    383:        (void)utimes(name, tv);
                    384: }
                    385:
                    386: /*
                    387:  * Examine the passed line buffer and
                    388:  * return true if it is all blanks and tabs.
                    389:  */
                    390: int
                    391: blankline(linebuf)
                    392:        char linebuf[];
                    393: {
                    394:        register char *cp;
                    395:
                    396:        for (cp = linebuf; *cp; cp++)
                    397:                if (*cp != ' ' && *cp != '\t')
                    398:                        return(0);
                    399:        return(1);
                    400: }
                    401:
                    402: /*
                    403:  * Get sender's name from this message.  If the message has
                    404:  * a bunch of arpanet stuff in it, we may have to skin the name
                    405:  * before returning it.
                    406:  */
                    407: char *
                    408: nameof(mp, reptype)
                    409:        register struct message *mp;
                    410:        int reptype;
                    411: {
                    412:        register char *cp, *cp2;
                    413:
                    414:        cp = skin(name1(mp, reptype));
                    415:        if (reptype != 0 || charcount(cp, '!') < 2)
                    416:                return(cp);
1.3       millert   417:        cp2 = strrchr(cp, '!');
1.1       deraadt   418:        cp2--;
                    419:        while (cp2 > cp && *cp2 != '!')
                    420:                cp2--;
                    421:        if (*cp2 == '!')
                    422:                return(cp2 + 1);
                    423:        return(cp);
                    424: }
                    425:
                    426: /*
                    427:  * Start of a "comment".
                    428:  * Ignore it.
                    429:  */
                    430: char *
                    431: skip_comment(cp)
                    432:        register char *cp;
                    433: {
                    434:        register nesting = 1;
                    435:
                    436:        for (; nesting > 0 && *cp; cp++) {
                    437:                switch (*cp) {
                    438:                case '\\':
                    439:                        if (cp[1])
                    440:                                cp++;
                    441:                        break;
                    442:                case '(':
                    443:                        nesting++;
                    444:                        break;
                    445:                case ')':
                    446:                        nesting--;
                    447:                        break;
                    448:                }
                    449:        }
1.5       millert   450:        return(cp);
1.1       deraadt   451: }
                    452:
                    453: /*
                    454:  * Skin an arpa net address according to the RFC 822 interpretation
                    455:  * of "host-phrase."
                    456:  */
                    457: char *
                    458: skin(name)
                    459:        char *name;
                    460: {
                    461:        register int c;
                    462:        register char *cp, *cp2;
                    463:        char *bufend;
                    464:        int gotlt, lastsp;
                    465:        char nbuf[BUFSIZ];
                    466:
                    467:        if (name == NOSTR)
                    468:                return(NOSTR);
1.3       millert   469:        if (strchr(name, '(') == NOSTR && strchr(name, '<') == NOSTR
                    470:            && strchr(name, ' ') == NOSTR)
1.1       deraadt   471:                return(name);
                    472:        gotlt = 0;
                    473:        lastsp = 0;
                    474:        bufend = nbuf;
1.2       deraadt   475:        for (cp = name, cp2 = bufend; (c = *cp++) != '\0'; ) {
1.1       deraadt   476:                switch (c) {
                    477:                case '(':
                    478:                        cp = skip_comment(cp);
                    479:                        lastsp = 0;
                    480:                        break;
                    481:
                    482:                case '"':
                    483:                        /*
                    484:                         * Start of a "quoted-string".
                    485:                         * Copy it in its entirety.
                    486:                         */
1.2       deraadt   487:                        while ((c = *cp) != '\0') {
1.1       deraadt   488:                                cp++;
                    489:                                if (c == '"')
                    490:                                        break;
                    491:                                if (c != '\\')
                    492:                                        *cp2++ = c;
1.2       deraadt   493:                                else if ((c = *cp) != '\0') {
1.1       deraadt   494:                                        *cp2++ = c;
                    495:                                        cp++;
                    496:                                }
                    497:                        }
                    498:                        lastsp = 0;
                    499:                        break;
                    500:
                    501:                case ' ':
                    502:                        if (cp[0] == 'a' && cp[1] == 't' && cp[2] == ' ')
                    503:                                cp += 3, *cp2++ = '@';
                    504:                        else
                    505:                        if (cp[0] == '@' && cp[1] == ' ')
                    506:                                cp += 2, *cp2++ = '@';
                    507:                        else
                    508:                                lastsp = 1;
                    509:                        break;
                    510:
                    511:                case '<':
                    512:                        cp2 = bufend;
                    513:                        gotlt++;
                    514:                        lastsp = 0;
                    515:                        break;
                    516:
                    517:                case '>':
                    518:                        if (gotlt) {
                    519:                                gotlt = 0;
                    520:                                while ((c = *cp) && c != ',') {
                    521:                                        cp++;
                    522:                                        if (c == '(')
                    523:                                                cp = skip_comment(cp);
                    524:                                        else if (c == '"')
1.2       deraadt   525:                                                while ((c = *cp) != '\0') {
1.1       deraadt   526:                                                        cp++;
                    527:                                                        if (c == '"')
                    528:                                                                break;
                    529:                                                        if (c == '\\' && *cp)
                    530:                                                                cp++;
                    531:                                                }
                    532:                                }
                    533:                                lastsp = 0;
                    534:                                break;
                    535:                        }
                    536:                        /* Fall into . . . */
                    537:
                    538:                default:
                    539:                        if (lastsp) {
                    540:                                lastsp = 0;
                    541:                                *cp2++ = ' ';
                    542:                        }
                    543:                        *cp2++ = c;
                    544:                        if (c == ',' && !gotlt) {
                    545:                                *cp2++ = ' ';
                    546:                                for (; *cp == ' '; cp++)
                    547:                                        ;
                    548:                                lastsp = 0;
                    549:                                bufend = cp2;
                    550:                        }
                    551:                }
                    552:        }
                    553:        *cp2 = 0;
                    554:
                    555:        return(savestr(nbuf));
                    556: }
                    557:
                    558: /*
                    559:  * Fetch the sender's name from the passed message.
                    560:  * Reptype can be
                    561:  *     0 -- get sender's name for display purposes
                    562:  *     1 -- get sender's name for reply
                    563:  *     2 -- get sender's name for Reply
                    564:  */
                    565: char *
                    566: name1(mp, reptype)
                    567:        register struct message *mp;
                    568:        int reptype;
                    569: {
                    570:        char namebuf[LINESIZE];
                    571:        char linebuf[LINESIZE];
                    572:        register char *cp, *cp2;
                    573:        register FILE *ibuf;
                    574:        int first = 1;
                    575:
                    576:        if ((cp = hfield("from", mp)) != NOSTR)
1.5       millert   577:                return(cp);
1.1       deraadt   578:        if (reptype == 0 && (cp = hfield("sender", mp)) != NOSTR)
1.5       millert   579:                return(cp);
1.1       deraadt   580:        ibuf = setinput(mp);
1.4       deraadt   581:        namebuf[0] = '\0';
1.1       deraadt   582:        if (readline(ibuf, linebuf, LINESIZE) < 0)
                    583:                return(savestr(namebuf));
                    584: newname:
                    585:        for (cp = linebuf; *cp && *cp != ' '; cp++)
                    586:                ;
                    587:        for (; *cp == ' ' || *cp == '\t'; cp++)
                    588:                ;
                    589:        for (cp2 = &namebuf[strlen(namebuf)];
                    590:             *cp && *cp != ' ' && *cp != '\t' && cp2 < namebuf + LINESIZE - 1;)
                    591:                *cp2++ = *cp++;
                    592:        *cp2 = '\0';
                    593:        if (readline(ibuf, linebuf, LINESIZE) < 0)
                    594:                return(savestr(namebuf));
1.3       millert   595:        if ((cp = strchr(linebuf, 'F')) == NULL)
1.1       deraadt   596:                return(savestr(namebuf));
                    597:        if (strncmp(cp, "From", 4) != 0)
                    598:                return(savestr(namebuf));
1.3       millert   599:        while ((cp = strchr(cp, 'r')) != NULL) {
1.1       deraadt   600:                if (strncmp(cp, "remote", 6) == 0) {
1.3       millert   601:                        if ((cp = strchr(cp, 'f')) == NULL)
1.1       deraadt   602:                                break;
                    603:                        if (strncmp(cp, "from", 4) != 0)
                    604:                                break;
1.3       millert   605:                        if ((cp = strchr(cp, ' ')) == NULL)
1.1       deraadt   606:                                break;
                    607:                        cp++;
                    608:                        if (first) {
1.5       millert   609:                                cp2 = namebuf;
1.1       deraadt   610:                                first = 0;
                    611:                        } else
1.5       millert   612:                                cp2 = strrchr(namebuf, '!') + 1;
                    613:                        strncpy(cp2, cp, sizeof(namebuf) - (cp2 - namebuf) - 2);
                    614:                        namebuf[sizeof(namebuf) - 2] = '\0';
1.1       deraadt   615:                        strcat(namebuf, "!");
                    616:                        goto newname;
                    617:                }
                    618:                cp++;
                    619:        }
                    620:        return(savestr(namebuf));
                    621: }
                    622:
                    623: /*
                    624:  * Count the occurances of c in str
                    625:  */
                    626: int
                    627: charcount(str, c)
                    628:        char *str;
                    629:        int c;
                    630: {
                    631:        register char *cp;
                    632:        register int i;
                    633:
                    634:        for (i = 0, cp = str; *cp; cp++)
                    635:                if (*cp == c)
                    636:                        i++;
                    637:        return(i);
                    638: }
                    639:
                    640: /*
                    641:  * Are any of the characters in the two strings the same?
                    642:  */
                    643: int
                    644: anyof(s1, s2)
                    645:        register char *s1, *s2;
                    646: {
                    647:
                    648:        while (*s1)
1.3       millert   649:                if (strchr(s2, *s1++))
1.5       millert   650:                        return(1);
                    651:        return(0);
1.1       deraadt   652: }
                    653:
                    654: /*
                    655:  * Convert c to upper case
                    656:  */
                    657: int
                    658: raise(c)
                    659:        register int c;
                    660: {
                    661:
                    662:        if (islower(c))
1.5       millert   663:                return(toupper(c));
                    664:        return(c);
1.1       deraadt   665: }
                    666:
                    667: /*
                    668:  * Copy s1 to s2, return pointer to null in s2.
                    669:  */
                    670: char *
                    671: copy(s1, s2)
                    672:        register char *s1, *s2;
                    673: {
                    674:
1.2       deraadt   675:        while ((*s2++ = *s1++) != '\0')
1.1       deraadt   676:                ;
1.5       millert   677:        return(s2 - 1);
1.1       deraadt   678: }
                    679:
                    680: /*
                    681:  * See if the given header field is supposed to be ignored.
                    682:  */
                    683: int
                    684: isign(field, ignore)
                    685:        char *field;
                    686:        struct ignoretab ignore[2];
                    687: {
1.5       millert   688:        char realfld[LINESIZE];
1.1       deraadt   689:
                    690:        if (ignore == ignoreall)
1.5       millert   691:                return(1);
1.1       deraadt   692:        /*
                    693:         * Lower-case the string, so that "Status" and "status"
                    694:         * will hash to the same place.
                    695:         */
                    696:        istrcpy(realfld, field);
                    697:        if (ignore[1].i_count > 0)
1.5       millert   698:                return(!member(realfld, ignore + 1));
1.1       deraadt   699:        else
1.5       millert   700:                return(member(realfld, ignore));
1.1       deraadt   701: }
                    702:
                    703: int
                    704: member(realfield, table)
                    705:        register char *realfield;
                    706:        struct ignoretab *table;
                    707: {
                    708:        register struct ignore *igp;
                    709:
                    710:        for (igp = table->i_head[hash(realfield)]; igp != 0; igp = igp->i_link)
                    711:                if (*igp->i_field == *realfield &&
                    712:                    equal(igp->i_field, realfield))
1.5       millert   713:                        return(1);
                    714:        return(0);
1.1       deraadt   715: }