Annotation of 42BSD/usr.lib/sendmail/src/headers.c, revision 1.1.1.1

1.1       root        1: # include <errno.h>
                      2: # include "sendmail.h"
                      3: 
                      4: SCCSID(@(#)headers.c   4.3             8/21/83);
                      5: 
                      6: /*
                      7: **  CHOMPHEADER -- process and save a header line.
                      8: **
                      9: **     Called by collect and by readcf to deal with header lines.
                     10: **
                     11: **     Parameters:
                     12: **             line -- header as a text line.
                     13: **             def -- if set, this is a default value.
                     14: **
                     15: **     Returns:
                     16: **             flags for this header.
                     17: **
                     18: **     Side Effects:
                     19: **             The header is saved on the header list.
                     20: **             Contents of 'line' are destroyed.
                     21: */
                     22: 
                     23: chompheader(line, def)
                     24:        char *line;
                     25:        bool def;
                     26: {
                     27:        register char *p;
                     28:        register HDR *h;
                     29:        HDR **hp;
                     30:        char *fname;
                     31:        char *fvalue;
                     32:        struct hdrinfo *hi;
                     33:        bool cond = FALSE;
                     34:        BITMAP mopts;
                     35:        extern char *crackaddr();
                     36: 
                     37: # ifdef DEBUG
                     38:        if (tTd(31, 6))
                     39:                printf("chompheader: %s\n", line);
                     40: # endif DEBUG
                     41: 
                     42:        /* strip off options */
                     43:        clrbitmap(mopts);
                     44:        p = line;
                     45:        if (*p == '?')
                     46:        {
                     47:                /* have some */
                     48:                register char *q = index(p + 1, *p);
                     49:                
                     50:                if (q != NULL)
                     51:                {
                     52:                        *q++ = '\0';
                     53:                        while (*++p != '\0')
                     54:                                setbitn(*p, mopts);
                     55:                        p = q;
                     56:                }
                     57:                else
                     58:                        syserr("chompheader: syntax error, line \"%s\"", line);
                     59:                cond = TRUE;
                     60:        }
                     61: 
                     62:        /* find canonical name */
                     63:        fname = p;
                     64:        p = index(p, ':');
                     65:        if (p == NULL)
                     66:        {
                     67:                syserr("chompheader: syntax error, line \"%s\"", line);
                     68:                return (0);
                     69:        }
                     70:        fvalue = &p[1];
                     71:        while (isspace(*--p))
                     72:                continue;
                     73:        *++p = '\0';
                     74:        makelower(fname);
                     75: 
                     76:        /* strip field value on front */
                     77:        if (*fvalue == ' ')
                     78:                fvalue++;
                     79: 
                     80:        /* see if it is a known type */
                     81:        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
                     82:        {
                     83:                if (strcmp(hi->hi_field, fname) == 0)
                     84:                        break;
                     85:        }
                     86: 
                     87:        /* see if this is a resent message */
                     88:        if (!def && bitset(H_RESENT, hi->hi_flags))
                     89:                CurEnv->e_flags |= EF_RESENT;
                     90: 
                     91:        /* if this means "end of header" quit now */
                     92:        if (bitset(H_EOH, hi->hi_flags))
                     93:                return (hi->hi_flags);
                     94: 
                     95:        /* drop explicit From: if same as what we would generate -- for MH */
                     96:        p = "resent-from";
                     97:        if (!bitset(EF_RESENT, CurEnv->e_flags))
                     98:                p += 7;
                     99:        if (!def && !QueueRun && strcmp(fname, p) == 0)
                    100:        {
                    101:                ADDRESS fromaddr;
                    102: 
                    103:                if (strcmp(fvalue, CurEnv->e_from.q_paddr) == 0)
                    104:                        return (hi->hi_flags);
                    105:        }
                    106: 
                    107:        /* delete default value for this header */
                    108:        for (hp = &CurEnv->e_header; (h = *hp) != NULL; hp = &h->h_link)
                    109:        {
                    110:                if (strcmp(fname, h->h_field) == 0 &&
                    111:                    bitset(H_DEFAULT, h->h_flags) &&
                    112:                    !bitset(H_FORCE, h->h_flags))
                    113:                        h->h_value = NULL;
                    114:        }
                    115: 
                    116:        /* create a new node */
                    117:        h = (HDR *) xalloc(sizeof *h);
                    118:        h->h_field = newstr(fname);
                    119:        h->h_value = NULL;
                    120:        h->h_link = NULL;
                    121:        bcopy(mopts, h->h_mflags, sizeof mopts);
                    122:        *hp = h;
                    123:        h->h_flags = hi->hi_flags;
                    124:        if (def)
                    125:                h->h_flags |= H_DEFAULT;
                    126:        if (cond)
                    127:                h->h_flags |= H_CHECK;
                    128:        if (h->h_value != NULL)
                    129:                free((char *) h->h_value);
                    130:        h->h_value = newstr(fvalue);
                    131: 
                    132:        /* hack to see if this is a new format message */
                    133:        if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
                    134:            (index(fvalue, ',') != NULL || index(fvalue, '(') != NULL ||
                    135:             index(fvalue, '<') != NULL || index(fvalue, ';') != NULL))
                    136:        {
                    137:                CurEnv->e_flags &= ~EF_OLDSTYLE;
                    138:        }
                    139: 
                    140:        return (h->h_flags);
                    141: }
                    142: /*
                    143: **  ADDHEADER -- add a header entry to the end of the queue.
                    144: **
                    145: **     This bypasses the special checking of chompheader.
                    146: **
                    147: **     Parameters:
                    148: **             field -- the name of the header field.
                    149: **             value -- the value of the field.  It must be lower-cased.
                    150: **             e -- the envelope to add them to.
                    151: **
                    152: **     Returns:
                    153: **             none.
                    154: **
                    155: **     Side Effects:
                    156: **             adds the field on the list of headers for this envelope.
                    157: */
                    158: 
                    159: addheader(field, value, e)
                    160:        char *field;
                    161:        char *value;
                    162:        ENVELOPE *e;
                    163: {
                    164:        register HDR *h;
                    165:        register struct hdrinfo *hi;
                    166:        HDR **hp;
                    167: 
                    168:        /* find info struct */
                    169:        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
                    170:        {
                    171:                if (strcmp(field, hi->hi_field) == 0)
                    172:                        break;
                    173:        }
                    174: 
                    175:        /* find current place in list -- keep back pointer? */
                    176:        for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
                    177:        {
                    178:                if (strcmp(field, h->h_field) == 0)
                    179:                        break;
                    180:        }
                    181: 
                    182:        /* allocate space for new header */
                    183:        h = (HDR *) xalloc(sizeof *h);
                    184:        h->h_field = field;
                    185:        h->h_value = newstr(value);
                    186:        h->h_link = *hp;
                    187:        h->h_flags = hi->hi_flags | H_DEFAULT;
                    188:        clrbitmap(h->h_mflags);
                    189:        *hp = h;
                    190: }
                    191: /*
                    192: **  HVALUE -- return value of a header.
                    193: **
                    194: **     Only "real" fields (i.e., ones that have not been supplied
                    195: **     as a default) are used.
                    196: **
                    197: **     Parameters:
                    198: **             field -- the field name.
                    199: **
                    200: **     Returns:
                    201: **             pointer to the value part.
                    202: **             NULL if not found.
                    203: **
                    204: **     Side Effects:
                    205: **             none.
                    206: */
                    207: 
                    208: char *
                    209: hvalue(field)
                    210:        char *field;
                    211: {
                    212:        register HDR *h;
                    213: 
                    214:        for (h = CurEnv->e_header; h != NULL; h = h->h_link)
                    215:        {
                    216:                if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
                    217:                        return (h->h_value);
                    218:        }
                    219:        return (NULL);
                    220: }
                    221: /*
                    222: **  ISHEADER -- predicate telling if argument is a header.
                    223: **
                    224: **     A line is a header if it has a single word followed by
                    225: **     optional white space followed by a colon.
                    226: **
                    227: **     Parameters:
                    228: **             s -- string to check for possible headerness.
                    229: **
                    230: **     Returns:
                    231: **             TRUE if s is a header.
                    232: **             FALSE otherwise.
                    233: **
                    234: **     Side Effects:
                    235: **             none.
                    236: */
                    237: 
                    238: bool
                    239: isheader(s)
                    240:        register char *s;
                    241: {
                    242:        while (*s > ' ' && *s != ':' && *s != '\0')
                    243:                s++;
                    244: 
                    245:        /* following technically violates RFC822 */
                    246:        while (isspace(*s))
                    247:                s++;
                    248: 
                    249:        return (*s == ':');
                    250: }
                    251: /*
                    252: **  EATHEADER -- run through the stored header and extract info.
                    253: **
                    254: **     Parameters:
                    255: **             e -- the envelope to process.
                    256: **
                    257: **     Returns:
                    258: **             none.
                    259: **
                    260: **     Side Effects:
                    261: **             Sets a bunch of global variables from information
                    262: **                     in the collected header.
                    263: **             Aborts the message if the hop count is exceeded.
                    264: */
                    265: 
                    266: eatheader(e)
                    267:        register ENVELOPE *e;
                    268: {
                    269:        register HDR *h;
                    270:        register char *p;
                    271:        int hopcnt = 0;
                    272: 
                    273: #ifdef DEBUG
                    274:        if (tTd(32, 1))
                    275:                printf("----- collected header -----\n");
                    276: #endif DEBUG
                    277:        for (h = e->e_header; h != NULL; h = h->h_link)
                    278:        {
                    279: #ifdef DEBUG
                    280:                extern char *capitalize();
                    281: 
                    282:                if (tTd(32, 1))
                    283:                        printf("%s: %s\n", capitalize(h->h_field), h->h_value);
                    284: #endif DEBUG
                    285:                /* count the number of times it has been processed */
                    286:                if (bitset(H_TRACE, h->h_flags))
                    287:                        hopcnt++;
                    288: 
                    289:                /* send to this person if we so desire */
                    290:                if (GrabTo && bitset(H_RCPT, h->h_flags) &&
                    291:                    !bitset(H_DEFAULT, h->h_flags) &&
                    292:                    (!bitset(EF_RESENT, CurEnv->e_flags) || bitset(H_RESENT, h->h_flags)))
                    293:                {
                    294:                        sendtolist(h->h_value, (ADDRESS *) NULL, &CurEnv->e_sendqueue);
                    295:                }
                    296: 
                    297:                /* log the message-id */
                    298: #ifdef LOG
                    299:                if (!QueueRun && LogLevel > 8 && h->h_value != NULL &&
                    300:                    strcmp(h->h_field, "message-id") == 0)
                    301:                {
                    302:                        char buf[MAXNAME];
                    303: 
                    304:                        p = h->h_value;
                    305:                        if (bitset(H_DEFAULT, h->h_flags))
                    306:                        {
                    307:                                expand(p, buf, &buf[sizeof buf], e);
                    308:                                p = buf;
                    309:                        }
                    310:                        syslog(LOG_INFO, "%s: message-id=%s", e->e_id, p);
                    311:                }
                    312: #endif LOG
                    313:        }
                    314: #ifdef DEBUG
                    315:        if (tTd(32, 1))
                    316:                printf("----------------------------\n");
                    317: #endif DEBUG
                    318: 
                    319:        /* store hop count */
                    320:        if (hopcnt > e->e_hopcount)
                    321:                e->e_hopcount = hopcnt;
                    322: 
                    323:        /* message priority */
                    324:        p = hvalue("precedence");
                    325:        if (p != NULL)
                    326:                e->e_class = priencode(p);
                    327:        if (!QueueRun)
                    328:                e->e_msgpriority = e->e_msgsize - e->e_class * WKPRIFACT;
                    329: 
                    330:        /* return receipt to */
                    331:        p = hvalue("return-receipt-to");
                    332:        if (p != NULL)
                    333:                e->e_receiptto = p;
                    334: 
                    335:        /* errors to */
                    336:        p = hvalue("errors-to");
                    337:        if (p != NULL)
                    338:                sendtolist(p, (ADDRESS *) NULL, &e->e_errorqueue);
                    339: 
                    340:        /* from person */
                    341:        if (OpMode == MD_ARPAFTP)
                    342:        {
                    343:                register struct hdrinfo *hi = HdrInfo;
                    344: 
                    345:                for (p = NULL; p == NULL && hi->hi_field != NULL; hi++)
                    346:                {
                    347:                        if (bitset(H_FROM, hi->hi_flags))
                    348:                                p = hvalue(hi->hi_field);
                    349:                }
                    350:                if (p != NULL)
                    351:                        setsender(p);
                    352:        }
                    353: 
                    354:        /* full name of from person */
                    355:        p = hvalue("full-name");
                    356:        if (p != NULL)
                    357:                define('x', p, e);
                    358: 
                    359:        /* date message originated */
                    360:        p = hvalue("posted-date");
                    361:        if (p == NULL)
                    362:                p = hvalue("date");
                    363:        if (p != NULL)
                    364:        {
                    365:                define('a', p, e);
                    366:                /* we don't have a good way to do canonical conversion ....
                    367:                define('d', newstr(arpatounix(p)), e);
                    368:                .... so we will ignore the problem for the time being */
                    369:        }
                    370: 
                    371:        /*
                    372:        **  Log collection information.
                    373:        */
                    374: 
                    375: # ifdef LOG
                    376:        if (!QueueRun && LogLevel > 1)
                    377:        {
                    378:                syslog(LOG_INFO, "%s: from=%s, size=%ld, class=%d\n",
                    379:                       CurEnv->e_id, CurEnv->e_from.q_paddr, CurEnv->e_msgsize,
                    380:                       CurEnv->e_class);
                    381:        }
                    382: # endif LOG
                    383: }
                    384: /*
                    385: **  PRIENCODE -- encode external priority names into internal values.
                    386: **
                    387: **     Parameters:
                    388: **             p -- priority in ascii.
                    389: **
                    390: **     Returns:
                    391: **             priority as a numeric level.
                    392: **
                    393: **     Side Effects:
                    394: **             none.
                    395: */
                    396: 
                    397: priencode(p)
                    398:        char *p;
                    399: {
                    400:        register int i;
                    401:        extern bool sameword();
                    402: 
                    403:        for (i = 0; i < NumPriorities; i++)
                    404:        {
                    405:                if (sameword(p, Priorities[i].pri_name))
                    406:                        return (Priorities[i].pri_val);
                    407:        }
                    408: 
                    409:        /* unknown priority */
                    410:        return (0);
                    411: }
                    412: /*
                    413: **  CRACKADDR -- parse an address and turn it into a macro
                    414: **
                    415: **     This doesn't actually parse the address -- it just extracts
                    416: **     it and replaces it with "$g".  The parse is totally ad hoc
                    417: **     and isn't even guaranteed to leave something syntactically
                    418: **     identical to what it started with.  However, it does leave
                    419: **     something semantically identical.
                    420: **
                    421: **     The process is kind of strange.  There are a number of
                    422: **     interesting cases:
                    423: **             1.  comment <address> comment   ==> comment <$g> comment
                    424: **             2.  address                     ==> address
                    425: **             3.  address (comment)           ==> $g (comment)
                    426: **             4.  (comment) address           ==> (comment) $g
                    427: **     And then there are the hard cases....
                    428: **             5.  add (comment) ress          ==> $g (comment)
                    429: **             6.  comment <address (comment)> ==> comment <$g (comment)>
                    430: **             7.    .... etc ....
                    431: **
                    432: **     Parameters:
                    433: **             addr -- the address to be cracked.
                    434: **
                    435: **     Returns:
                    436: **             a pointer to the new version.
                    437: **
                    438: **     Side Effects:
                    439: **             none.
                    440: **
                    441: **     Warning:
                    442: **             The return value is saved in local storage and should
                    443: **             be copied if it is to be reused.
                    444: */
                    445: 
                    446: char *
                    447: crackaddr(addr)
                    448:        register char *addr;
                    449: {
                    450:        register char *p;
                    451:        register int i;
                    452:        static char buf[MAXNAME];
                    453:        char *rhs;
                    454:        bool gotaddr;
                    455:        register char *bp;
                    456: 
                    457: # ifdef DEBUG
                    458:        if (tTd(33, 1))
                    459:                printf("crackaddr(%s)\n", addr);
                    460: # endif DEBUG
                    461: 
                    462:        strcpy(buf, "");
                    463:        rhs = NULL;
                    464: 
                    465:        /* strip leading spaces */
                    466:        while (*addr != '\0' && isspace(*addr))
                    467:                addr++;
                    468: 
                    469:        /*
                    470:        **  See if we have anything in angle brackets.  If so, that is
                    471:        **  the address part, and the rest is the comment.
                    472:        */
                    473: 
                    474:        p = index(addr, '<');
                    475:        if (p != NULL)
                    476:        {
                    477:                /* copy the beginning of the addr field to the buffer */
                    478:                *p = '\0';
                    479:                strcpy(buf, addr);
                    480:                strcat(buf, "<");
                    481:                *p++ = '<';
                    482: 
                    483:                /* skip spaces */
                    484:                while (isspace(*p))
                    485:                        p++;
                    486: 
                    487:                /* find the matching right angle bracket */
                    488:                addr = p;
                    489:                for (i = 0; *p != '\0'; p++)
                    490:                {
                    491:                        switch (*p)
                    492:                        {
                    493:                          case '<':
                    494:                                i++;
                    495:                                break;
                    496: 
                    497:                          case '>':
                    498:                                i--;
                    499:                                break;
                    500:                        }
                    501:                        if (i < 0)
                    502:                                break;
                    503:                }
                    504: 
                    505:                /* p now points to the closing quote (or a null byte) */
                    506:                if (*p != '\0')
                    507:                {
                    508:                        /* make rhs point to the extra stuff at the end */
                    509:                        rhs = p;
                    510:                        *p++ = '\0';
                    511:                }
                    512:        }
                    513: 
                    514:        /*
                    515:        **  Now parse the real address part.  "addr" points to the (null
                    516:        **  terminated) version of what we are inerested in; rhs points
                    517:        **  to the extra stuff at the end of the line, if any.
                    518:        */
                    519: 
                    520:        p = addr;
                    521: 
                    522:        /* now strip out comments */
                    523:        bp = &buf[strlen(buf)];
                    524:        gotaddr = FALSE;
                    525:        for (; *p != '\0'; p++)
                    526:        {
                    527:                if (*p == '(')
                    528:                {
                    529:                        /* copy to matching close paren */
                    530:                        *bp++ = *p++;
                    531:                        for (i = 0; *p != '\0'; p++)
                    532:                        {
                    533:                                *bp++ = *p;
                    534:                                switch (*p)
                    535:                                {
                    536:                                  case '(':
                    537:                                        i++;
                    538:                                        break;
                    539: 
                    540:                                  case ')':
                    541:                                        i--;
                    542:                                        break;
                    543:                                }
                    544:                                if (i < 0)
                    545:                                        break;
                    546:                        }
                    547:                        continue;
                    548:                }
                    549: 
                    550:                /*
                    551:                **  If this is the first "real" character we have seen,
                    552:                **  then we put the "$g" in the buffer now.
                    553:                */
                    554: 
                    555:                if (isspace(*p))
                    556:                        *bp++ = *p;
                    557:                else if (!gotaddr)
                    558:                {
                    559:                        strcpy(bp, "$g");
                    560:                        bp += 2;
                    561:                        gotaddr = TRUE;
                    562:                }
                    563:        }
                    564: 
                    565:        /* hack, hack.... strip trailing blanks */
                    566:        do
                    567:        {
                    568:                *bp-- = '\0';
                    569:        } while (isspace(*bp));
                    570:        bp++;
                    571: 
                    572:        /* put any right hand side back on */
                    573:        if (rhs != NULL)
                    574:        {
                    575:                *rhs = '>';
                    576:                strcpy(bp, rhs);
                    577:        }
                    578: 
                    579: # ifdef DEBUG
                    580:        if (tTd(33, 1))
                    581:                printf("crackaddr=>`%s'\n", buf);
                    582: # endif DEBUG
                    583: 
                    584:        return (buf);
                    585: }
                    586: /*
                    587: **  PUTHEADER -- put the header part of a message from the in-core copy
                    588: **
                    589: **     Parameters:
                    590: **             fp -- file to put it on.
                    591: **             m -- mailer to use.
                    592: **             e -- envelope to use.
                    593: **
                    594: **     Returns:
                    595: **             none.
                    596: **
                    597: **     Side Effects:
                    598: **             none.
                    599: */
                    600: 
                    601: putheader(fp, m, e)
                    602:        register FILE *fp;
                    603:        register MAILER *m;
                    604:        register ENVELOPE *e;
                    605: {
                    606:        char buf[BUFSIZ];
                    607:        register HDR *h;
                    608:        extern char *arpadate();
                    609:        extern char *capitalize();
                    610:        char obuf[MAXLINE];
                    611: 
                    612:        for (h = e->e_header; h != NULL; h = h->h_link)
                    613:        {
                    614:                register char *p;
                    615:                extern bool bitintersect();
                    616: 
                    617:                if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
                    618:                    !bitintersect(h->h_mflags, m->m_flags))
                    619:                        continue;
                    620: 
                    621:                /* handle Resent-... headers specially */
                    622:                if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
                    623:                        continue;
                    624: 
                    625:                p = h->h_value;
                    626:                if (bitset(H_DEFAULT, h->h_flags))
                    627:                {
                    628:                        /* macro expand value if generated internally */
                    629:                        expand(p, buf, &buf[sizeof buf], e);
                    630:                        p = buf;
                    631:                        if (p == NULL || *p == '\0')
                    632:                                continue;
                    633:                }
                    634: 
                    635:                if (bitset(H_FROM|H_RCPT, h->h_flags))
                    636:                {
                    637:                        /* address field */
                    638:                        bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
                    639: 
                    640:                        if (bitset(H_FROM, h->h_flags))
                    641:                                oldstyle = FALSE;
                    642:                        commaize(h, p, fp, oldstyle, m);
                    643:                }
                    644:                else
                    645:                {
                    646:                        /* vanilla header line */
                    647:                        register char *nlp;
                    648: 
                    649:                        (void) sprintf(obuf, "%s: ", capitalize(h->h_field));
                    650:                        while ((nlp = index(p, '\n')) != NULL)
                    651:                        {
                    652:                                *nlp = '\0';
                    653:                                (void) strcat(obuf, p);
                    654:                                *nlp = '\n';
                    655:                                putline(obuf, fp, m);
                    656:                                p = ++nlp;
                    657:                                obuf[0] = '\0';
                    658:                        }
                    659:                        (void) strcat(obuf, p);
                    660:                        putline(obuf, fp, m);
                    661:                }
                    662:        }
                    663: }
                    664: /*
                    665: **  COMMAIZE -- output a header field, making a comma-translated list.
                    666: **
                    667: **     Parameters:
                    668: **             h -- the header field to output.
                    669: **             p -- the value to put in it.
                    670: **             fp -- file to put it to.
                    671: **             oldstyle -- TRUE if this is an old style header.
                    672: **             m -- a pointer to the mailer descriptor.  If NULL,
                    673: **                     don't transform the name at all.
                    674: **
                    675: **     Returns:
                    676: **             none.
                    677: **
                    678: **     Side Effects:
                    679: **             outputs "p" to file "fp".
                    680: */
                    681: 
                    682: commaize(h, p, fp, oldstyle, m)
                    683:        register HDR *h;
                    684:        register char *p;
                    685:        FILE *fp;
                    686:        bool oldstyle;
                    687:        register MAILER *m;
                    688: {
                    689:        register char *obp;
                    690:        int opos;
                    691:        bool firstone = TRUE;
                    692:        char obuf[MAXLINE + 3];
                    693: 
                    694:        /*
                    695:        **  Output the address list translated by the
                    696:        **  mailer and with commas.
                    697:        */
                    698: 
                    699: # ifdef DEBUG
                    700:        if (tTd(14, 2))
                    701:                printf("commaize(%s: %s)\n", h->h_field, p);
                    702: # endif DEBUG
                    703: 
                    704:        obp = obuf;
                    705:        (void) sprintf(obp, "%s: ", capitalize(h->h_field));
                    706:        opos = strlen(h->h_field) + 2;
                    707:        obp += opos;
                    708: 
                    709:        /*
                    710:        **  Run through the list of values.
                    711:        */
                    712: 
                    713:        while (*p != '\0')
                    714:        {
                    715:                register char *name;
                    716:                char savechar;
                    717:                extern char *remotename();
                    718:                extern char *DelimChar;         /* defined in prescan */
                    719: 
                    720:                /*
                    721:                **  Find the end of the name.  New style names
                    722:                **  end with a comma, old style names end with
                    723:                **  a space character.  However, spaces do not
                    724:                **  necessarily delimit an old-style name -- at
                    725:                **  signs mean keep going.
                    726:                */
                    727: 
                    728:                /* find end of name */
                    729:                while (isspace(*p) || *p == ',')
                    730:                        p++;
                    731:                name = p;
                    732:                for (;;)
                    733:                {
                    734:                        char *oldp;
                    735:                        extern bool isatword();
                    736:                        extern char **prescan();
                    737: 
                    738:                        (void) prescan(p, oldstyle ? ' ' : ',');
                    739:                        p = DelimChar;
                    740: 
                    741:                        /* look to see if we have an at sign */
                    742:                        oldp = p;
                    743:                        while (*p != '\0' && isspace(*p))
                    744:                                p++;
                    745: 
                    746:                        if (*p != '@' && !isatword(p))
                    747:                        {
                    748:                                p = oldp;
                    749:                                break;
                    750:                        }
                    751:                        p += *p == '@' ? 1 : 2;
                    752:                        while (*p != '\0' && isspace(*p))
                    753:                                p++;
                    754:                }
                    755:                /* at the end of one complete name */
                    756: 
                    757:                /* strip off trailing white space */
                    758:                while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
                    759:                        p--;
                    760:                if (++p == name)
                    761:                        continue;
                    762:                savechar = *p;
                    763:                *p = '\0';
                    764: 
                    765:                /* translate the name to be relative */
                    766:                name = remotename(name, m, bitset(H_FROM, h->h_flags), FALSE);
                    767:                if (*name == '\0')
                    768:                {
                    769:                        *p = savechar;
                    770:                        continue;
                    771:                }
                    772: 
                    773:                /* output the name with nice formatting */
                    774:                opos += qstrlen(name);
                    775:                if (!firstone)
                    776:                        opos += 2;
                    777:                if (opos > 78 && !firstone)
                    778:                {
                    779:                        (void) strcpy(obp, ",\n");
                    780:                        putline(obuf, fp, m);
                    781:                        obp = obuf;
                    782:                        (void) sprintf(obp, "        ");
                    783:                        opos = strlen(obp);
                    784:                        obp += opos;
                    785:                        opos += qstrlen(name);
                    786:                }
                    787:                else if (!firstone)
                    788:                {
                    789:                        (void) sprintf(obp, ", ");
                    790:                        obp += 2;
                    791:                }
                    792: 
                    793:                /* strip off quote bits as we output */
                    794:                while (*name != '\0' && obp < &obuf[MAXLINE])
                    795:                {
                    796:                        if (bitset(0200, *name))
                    797:                                *obp++ = '\\';
                    798:                        *obp++ = *name++ & ~0200;
                    799:                }
                    800:                firstone = FALSE;
                    801:                *p = savechar;
                    802:        }
                    803:        (void) strcpy(obp, "\n");
                    804:        putline(obuf, fp, m);
                    805: }
                    806: /*
                    807: **  ISATWORD -- tell if the word we are pointing to is "at".
                    808: **
                    809: **     Parameters:
                    810: **             p -- word to check.
                    811: **
                    812: **     Returns:
                    813: **             TRUE -- if p is the word at.
                    814: **             FALSE -- otherwise.
                    815: **
                    816: **     Side Effects:
                    817: **             none.
                    818: */
                    819: 
                    820: bool
                    821: isatword(p)
                    822:        register char *p;
                    823: {
                    824:        extern char lower();
                    825: 
                    826:        if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
                    827:            p[2] != '\0' && isspace(p[2]))
                    828:                return (TRUE);
                    829:        return (FALSE);
                    830: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.