Annotation of 43BSDReno/contrib/mh/zotnet/mf/mf.c, revision 1.1.1.1

1.1       root        1: /* mf.c - mail filter subroutines */
                      2: 
                      3: #include "mf.h"
                      4: #include <ctype.h>
                      5: #include <stdio.h>
                      6: 
                      7: static int compress(), isat(), parse_address(), phrase(), route_addr(),
                      8:     local_part(), domain(), route(), my_lex();
                      9: 
                     10: /*  */
                     11: 
                     12: static char *
                     13: getcpy(s)
                     14:        register char *s;
                     15: {
                     16:     register char   *p;
                     17: 
                     18: if (!s) { _cleanup(); abort(); for(;;) pause();}
                     19:     if ((p = malloc ((unsigned) (strlen (s) + 2))) != NULL)
                     20:        (void) strcpy (p, s);
                     21:     return p;
                     22: }
                     23: 
                     24: 
                     25: static char *
                     26: add(s1, s2)
                     27:        register char *s1, *s2;
                     28: {
                     29:     register char   *p;
                     30: 
                     31:     if (s2 == NULL)
                     32:        return getcpy (s1);
                     33: 
                     34:     if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) != NULL)
                     35:        (void) sprintf (p, "%s%s", s2, s1);
                     36:     free (s2);
                     37:     return p;
                     38: }
                     39: 
                     40: /*  */
                     41: 
                     42: isfrom(string)
                     43:        register char *string;
                     44: {
                     45:     return (strncmp (string, "From ", 5) == 0
                     46:            || strncmp (string, ">From ", 6) == 0);
                     47: }
                     48: 
                     49: 
                     50: lequal(a, b)
                     51:        register char *a, *b;
                     52: {
                     53:     for (; *a; a++, b++)
                     54:        if (*b == NULL)
                     55:            return FALSE;
                     56:        else {
                     57:            char    c1 = islower (*a) ? toupper (*a) : *a;
                     58:            char    c2 = islower (*b) ? toupper (*b) : *b;
                     59:            if (c1 != c2)
                     60:                return FALSE;
                     61:        }
                     62: 
                     63:     return (*b == NULL);
                     64: }
                     65: 
                     66: /*  */
                     67: 
                     68: /*
                     69:  *
                     70:  * seekadrx() is tricky.  We want to cover both UUCP-style and ARPA-style
                     71:  * addresses, so for each list of addresses we see if we can find some
                     72:  * character to give us a hint.
                     73:  *
                     74:  */
                     75: 
                     76: 
                     77: #define        CHKADR  0               /* undertermined address style */
                     78: #define        UNIXDR  1               /* UNIX-style address */
                     79: #define        ARPADR  2               /* ARPAnet-style address */
                     80: 
                     81: 
                     82: static char *punctuators = ";<>.()[]";
                     83: static char *vp = NULL;
                     84: static char *tp = NULL;
                     85: 
                     86: static struct adrx  adrxs1;
                     87: 
                     88: /*  */
                     89: 
                     90: struct adrx *
                     91: seekadrx(addrs)
                     92:        register char *addrs;
                     93: {
                     94:     static int  state = CHKADR;
                     95:     register char   *cp;
                     96:     register struct adrx *adrxp;
                     97: 
                     98:     if (state == CHKADR)
                     99:        for (state = UNIXDR, cp = addrs; *cp; cp++)
                    100:            if (index (punctuators, *cp)) {
                    101:                state = ARPADR;
                    102:                break;
                    103:            }
                    104: 
                    105:     switch (state) {
                    106:        case UNIXDR:
                    107:            adrxp = uucpadrx (addrs);
                    108:            break;
                    109: 
                    110:        case ARPADR:
                    111:        default:
                    112:            adrxp = getadrx (addrs);
                    113:            break;
                    114:     }
                    115: 
                    116:     if (adrxp == NULL)
                    117:        state = CHKADR;
                    118: 
                    119:     return adrxp;
                    120: }
                    121: 
                    122: /*  */
                    123: 
                    124: /*
                    125:  *
                    126:  * uucpadrx() implements a partial UUCP-style address parser.  It's based
                    127:  * on the UUCP notion that addresses are separated by spaces or commas.
                    128:  *
                    129:  */
                    130: 
                    131: 
                    132: struct adrx *
                    133: uucpadrx(addrs)
                    134:        register char *addrs;
                    135: {
                    136:     register char  *cp,
                    137:                    *wp,
                    138:                    *xp,
                    139:                    *yp,
                    140:                    *zp;
                    141:     register struct adrx   *adrxp = &adrxs1;
                    142: 
                    143:     if (vp == NULL) {
                    144:        vp = tp = getcpy (addrs);
                    145:        compress (addrs, vp);
                    146:     }
                    147:     else
                    148:        if (tp == NULL) {
                    149:            free (vp);
                    150:            vp = NULL;
                    151:            return NULL;
                    152:        }
                    153: 
                    154:     for (cp = tp; isspace (*cp); cp++)
                    155:        continue;
                    156:     if (*cp == NULL) {
                    157:        free (vp);
                    158:        vp = tp = NULL;
                    159:        return NULL;
                    160:     }
                    161: 
                    162: /*  */
                    163: 
                    164:     if ((wp = index (cp, ',')) == NULL)
                    165:        if ((wp = index (cp, ' ')) != NULL) {
                    166:            xp = wp;
                    167:            while (isspace (*xp))
                    168:                xp++;
                    169:            if (*xp != NULL && isat (--xp)) {
                    170:                yp = xp + 4;
                    171:                while (isspace (*yp))
                    172:                    yp++;
                    173:                if (*yp != NULL)
                    174:                    if ((zp = index (yp, ' ')) != NULL)
                    175:                        *zp = NULL, tp = ++zp;
                    176:                    else
                    177:                        tp = NULL;
                    178:                else
                    179:                    *wp = NULL, tp = ++wp;
                    180:            }
                    181:            else
                    182:                *wp = NULL, tp = ++wp;
                    183:        }
                    184:        else
                    185:            tp = NULL;
                    186:     else
                    187:        *wp = NULL, tp = ++wp;
                    188: 
                    189:     if (adrxp -> text)
                    190:        free (adrxp -> text);
                    191:     adrxp -> text = getcpy (cp);
                    192:     adrxp -> mbox = cp;
                    193:     adrxp -> host = adrxp -> path = NULL;
                    194:     if ((wp = rindex (cp, '@')) != NULL) {
                    195:        *wp++ = NULL;
                    196:        adrxp -> host = *wp ? wp : NULL;
                    197:     }
                    198:     else
                    199:        for (wp = cp + strlen (cp) - 4; wp >= cp; wp--)
                    200:            if (isat (wp)) {
                    201:                *wp++ = NULL;
                    202:                adrxp -> host = wp + 3;
                    203:            }
                    204: 
                    205:     adrxp -> pers = adrxp -> grp = adrxp -> note = adrxp -> err = NULL;
                    206:     adrxp -> ingrp = 0;
                    207: 
                    208:     return adrxp;
                    209: }
                    210: 
                    211: /*  */
                    212: 
                    213: static int
                    214: compress(fp, tp)
                    215:        register char *fp, *tp;
                    216: {
                    217:     register char   c,
                    218:                    *cp;
                    219: 
                    220:     for (c = ' ', cp = tp; (*tp = *fp++) != NULL;)
                    221:        if (isspace (*tp)) {
                    222:            if (c != ' ')
                    223:                *tp++ = c = ' ';
                    224:        }
                    225:        else
                    226:            c = *tp++;
                    227: 
                    228:     if (c == ' ' && cp < tp)
                    229:        *--tp = NULL;
                    230: }
                    231: 
                    232: 
                    233: static int
                    234: isat(p)
                    235:        register char *p;
                    236: {
                    237:     return (strncmp (p, " AT ", 4)
                    238:            && strncmp (p, " At ", 4)
                    239:            && strncmp (p, " aT ", 4)
                    240:            && strncmp (p, " at ", 4) ? FALSE : TRUE);
                    241: }
                    242: 
                    243: /*  */
                    244: 
                    245: /*
                    246:  *
                    247:  * getadrx() implements a partial 822-style address parser.  The parser
                    248:  * is neither complete nor correct.  It does however recognize nearly all
                    249:  * of the 822 address syntax.  In addition it handles the majority of the
                    250:  * 733 syntax as well.  Most problems arise from trying to accomodate both.
                    251:  *
                    252:  * In terms of 822, the route-specification in
                    253:  *
                    254:  *              "<" [route] local-part "@" domain ">"
                    255:  *
                    256:  * is parsed and returned unchanged.  Multiple at-signs are compressed
                    257:  * via source-routing.  Recursive groups are not allowed as per the
                    258:  * standard.
                    259:  *
                    260:  * In terms of 733, " at " is recognized as equivalent to "@".
                    261:  *
                    262:  * In terms of both the parser will not complain about missing hosts.
                    263:  *
                    264:  * -----
                    265:  *
                    266:  * We should not allow addresses like
                    267:  *
                    268:  *             Marshall T. Rose <MRose@UCI>
                    269:  *
                    270:  * but should insist on
                    271:  *
                    272:  *             "Marshall T. Rose" <MRose@UCI>
                    273:  *
                    274:  * Unfortunately, a lot of mailers stupidly let people get away with this.
                    275:  *
                    276:  * -----
                    277:  *
                    278:  * We should not allow addresses like
                    279:  *
                    280:  *             <MRose@UCI>
                    281:  *
                    282:  * but should insist on
                    283:  *
                    284:  *             MRose@UCI
                    285:  *
                    286:  * Unfortunately, a lot of mailers stupidly let people's UAs get away with
                    287:  * this.
                    288:  *
                    289:  * -----
                    290:  *
                    291:  * We should not allow addresses like
                    292:  *
                    293:  *             @UCI:MRose@UCI-750a
                    294:  *
                    295:  * but should insist on
                    296:  *
                    297:  *             Marshall Rose <@UCI:MRose@UCI-750a>
                    298:  *
                    299:  * Unfortunately, a lot of mailers stupidly do this.
                    300:  *
                    301:  */
                    302: 
                    303: /*  */
                    304: 
                    305: #define        QUOTE   '\\'
                    306: 
                    307: #define        LX_END  0
                    308: #define        LX_ERR  1
                    309: #define        LX_ATOM 2
                    310: #define        LX_QSTR 3
                    311: #define        LX_DLIT 4
                    312: #define        LX_SEMI 5
                    313: #define        LX_COMA 6
                    314: #define        LX_LBRK 7
                    315: #define        LX_RBRK 8
                    316: #define        LX_COLN 9
                    317: #define        LX_DOT  10
                    318: #define        LX_AT   11
                    319: 
                    320: static struct {
                    321:     char    lx_chr;
                    322:     int     lx_val;
                    323: }               special[] = {
                    324:                     ';', LX_SEMI,
                    325:                     ',', LX_COMA,
                    326:                     '<', LX_LBRK,
                    327:                     '>', LX_RBRK,
                    328:                     ':', LX_COLN,
                    329:                     '.', LX_DOT,
                    330:                     '@', LX_AT,
                    331:                     '(', LX_ERR,
                    332:                     ')', LX_ERR,
                    333:                     QUOTE, LX_ERR,
                    334:                     '"', LX_ERR,
                    335:                     '[', LX_ERR,
                    336:                     ']', LX_ERR,
                    337:                     NULL, NULL
                    338: };
                    339: 
                    340: /*  */
                    341: 
                    342: static int  glevel = 0;
                    343: static int  ingrp = 0;
                    344: static int  last_lex = LX_END;
                    345: 
                    346: static char *dp = NULL;
                    347: static char *cp = NULL;
                    348: static char *ap = NULL;
                    349: static char *pers = NULL;
                    350: static char *mbox = NULL;
                    351: static char *host = NULL;
                    352: static char *path = NULL;
                    353: static char *grp = NULL;
                    354: static char *note = NULL;
                    355: static char err[BUFSIZ];
                    356: static char adr[BUFSIZ];
                    357: 
                    358: static struct adrx  adrxs2;
                    359: 
                    360: /*  */
                    361: 
                    362: struct adrx *
                    363: getadrx(addrs)
                    364:        register char *addrs;
                    365: {
                    366:     register char   *bp;
                    367:     register struct adrx *adrxp = &adrxs2;
                    368: 
                    369:     if (pers)
                    370:        free (pers);
                    371:     if (mbox)
                    372:        free (mbox);
                    373:     if (host)
                    374:        free (host);
                    375:     if (path)
                    376:        free (path);
                    377:     if (grp)
                    378:        free (grp);
                    379:     if (note)
                    380:        free (note);
                    381:     pers = mbox = host = path = grp = note = NULL;
                    382:     err[0] = NULL;
                    383: 
                    384:     if (dp == NULL) {
                    385:        dp = cp = getcpy (addrs ? addrs : "");
                    386:        glevel = 0;
                    387:     }
                    388:     else
                    389:        if (cp == NULL) {
                    390:            free (dp);
                    391:            dp = NULL;
                    392:            return NULL;
                    393:        }
                    394: 
                    395:     switch (parse_address ()) {
                    396:        case DONE:
                    397:            free (dp);
                    398:            dp = cp = NULL;
                    399:            return NULL;
                    400: 
                    401:        case OK:
                    402:            switch (last_lex) {
                    403:                case LX_COMA:
                    404:                case LX_END:
                    405:                    break;
                    406: 
                    407:                default:        /* catch trailing comments */
                    408:                    bp = cp;
                    409:                    (void) my_lex (adr);
                    410:                    cp = bp;
                    411:                    break;
                    412:            }
                    413:            break;
                    414: 
                    415:        default:
                    416:            break;
                    417:        }
                    418: 
                    419:     if (err[0])
                    420:        for (;;) {
                    421:            switch (last_lex) {
                    422:                case LX_COMA:
                    423:                case LX_END:
                    424:                    break;
                    425: 
                    426:                default:
                    427:                    (void) my_lex (adr);
                    428:                    continue;
                    429:            }
                    430:            break;
                    431:        }
                    432:     while (isspace (*ap))
                    433:        ap++;
                    434:     if (cp)
                    435:        (void) sprintf (adr, "%.*s", cp - ap, ap);
                    436:     else
                    437:        (void) strcpy (adr, ap);
                    438:     bp = adr + strlen (adr) - 1;
                    439:     if (*bp == ',' || *bp == ';' || *bp == '\n')
                    440:        *bp = NULL;
                    441: 
                    442: /*  */
                    443: 
                    444:     adrxp -> text = adr;
                    445:     adrxp -> pers = pers;
                    446:     adrxp -> mbox = mbox;
                    447:     adrxp -> host = host;
                    448:     adrxp -> path = path;
                    449:     adrxp -> grp = grp;
                    450:     adrxp -> ingrp = ingrp;
                    451:     adrxp -> note = note;
                    452:     adrxp -> err = err[0] ? err : NULL;
                    453: 
                    454:     return adrxp;
                    455: }
                    456: 
                    457: /*  */
                    458: 
                    459: static int
                    460: parse_address()
                    461: {
                    462:     char    buffer[BUFSIZ];
                    463: 
                    464: again: ;
                    465:     ap = cp;
                    466:     switch (my_lex (buffer)) {
                    467:        case LX_ATOM:
                    468:        case LX_QSTR:
                    469:            pers = getcpy (buffer);
                    470:            break;
                    471: 
                    472:        case LX_SEMI:
                    473:            if (glevel-- <= 0) {
                    474:                (void) strcpy (err, "extraneous semi-colon");
                    475:                return NOTOK;
                    476:            }
                    477:        case LX_COMA:
                    478:            if (note) {
                    479:                free (note);
                    480:                note = NULL;
                    481:            }
                    482:            goto again;
                    483: 
                    484:        case LX_END:
                    485:            return DONE;
                    486: 
                    487:        case LX_LBRK:           /* sigh (2) */
                    488:            goto get_addr;
                    489: 
                    490:        case LX_AT:             /* sigh (3) */
                    491:            cp = ap;
                    492:            if (route_addr (buffer) == NOTOK)
                    493:                return NOTOK;
                    494:            return OK;          /* why be choosy? */
                    495: 
                    496:        default:
                    497:            (void) sprintf (err, "illegal address construct (%s)", buffer);
                    498:            return NOTOK;
                    499:     }
                    500: 
                    501: /*  */
                    502: 
                    503:     switch (my_lex (buffer)) {
                    504:        case LX_ATOM:
                    505:        case LX_QSTR:
                    506:            pers = add (buffer, add (" ", pers));
                    507:     more_phrase: ;             /* sigh (1) */
                    508:            if (phrase (buffer) == NOTOK)
                    509:                return NOTOK;
                    510: 
                    511:            switch (last_lex) {
                    512:                case LX_LBRK:
                    513:            get_addr: ;
                    514:                    if (route_addr (buffer) == NOTOK)
                    515:                        return NOTOK;
                    516:                    if (last_lex == LX_RBRK)
                    517:                        return OK;
                    518:                    (void) sprintf (err, "missing right-bracket (%s)", buffer);
                    519:                    return NOTOK;
                    520: 
                    521:                case LX_COLN:
                    522:            get_group: ;
                    523:                    if (glevel++ > 0) {
                    524:                        (void) sprintf (err, "nested groups not allowed (%s)",
                    525:                                pers);
                    526:                        return NOTOK;
                    527:                    }
                    528:                    grp = add (": ", pers);
                    529:                    pers = NULL;
                    530:                    {
                    531:                        char   *pp = cp;
                    532: 
                    533:                        for (;;)
                    534:                            switch (my_lex (buffer)) {
                    535:                                case LX_SEMI:
                    536:                                case LX_END: /* tsk, tsk */
                    537:                                    glevel--;
                    538:                                    return OK;
                    539: 
                    540:                                case LX_COMA:
                    541:                                    continue;
                    542: 
                    543:                                default:
                    544:                                    cp = pp;
                    545:                                    return parse_address ();
                    546:                            }
                    547:                    }
                    548: 
                    549:                case LX_DOT:    /* sigh (1) */
                    550:                    pers = add (".", pers);
                    551:                    goto more_phrase;
                    552: 
                    553:                default:
                    554:                    (void) sprintf (err,
                    555:                            "no mailbox in address, only a phrase (%s%s)",
                    556:                            pers, buffer);
                    557:                    return NOTOK;
                    558:            }
                    559: 
                    560: /*  */
                    561: 
                    562:        case LX_LBRK:
                    563:            goto get_addr;
                    564: 
                    565:        case LX_COLN:
                    566:            goto get_group;
                    567: 
                    568:        case LX_DOT:
                    569:            mbox = add (buffer, pers);
                    570:            pers = NULL;
                    571:            if (route_addr (buffer) == NOTOK)
                    572:                return NOTOK;
                    573:            goto check_end;
                    574: 
                    575:        case LX_AT:
                    576:            ingrp = glevel;
                    577:            mbox = pers;
                    578:            pers = NULL;
                    579:            if (domain (buffer) == NOTOK)
                    580:                return NOTOK;
                    581:     check_end: ;
                    582:            switch (last_lex) {
                    583:                case LX_SEMI:
                    584:                    if (glevel-- <= 0) {
                    585:                        (void) strcpy (err, "extraneous semi-colon");
                    586:                        return NOTOK;
                    587:                    }
                    588:                case LX_COMA:
                    589:                case LX_END:
                    590:                    return OK;
                    591: 
                    592:                default:
                    593:                    (void) sprintf (err, "junk after local@domain (%s)",
                    594:                            buffer);
                    595:                    return NOTOK;
                    596:            }
                    597: 
                    598:        case LX_SEMI:           /* no host */
                    599:        case LX_COMA:
                    600:        case LX_END:
                    601:            ingrp = glevel;
                    602:            if (last_lex == LX_SEMI && glevel-- <= 0) {
                    603:                (void) strcpy (err, "extraneous semi-colon");
                    604:                return NOTOK;
                    605:            }
                    606:            mbox = pers;
                    607:            pers = NULL;
                    608:            return OK;
                    609: 
                    610:        default:
                    611:            (void) sprintf (err, "missing mailbox (%s)", buffer);
                    612:            return NOTOK;
                    613:     }
                    614: }
                    615: 
                    616: /*  */
                    617: 
                    618: static int
                    619: phrase(buffer)
                    620:        register char *buffer;
                    621: {
                    622:     for (;;)
                    623:        switch (my_lex (buffer)) {
                    624:            case LX_ATOM:
                    625:            case LX_QSTR:
                    626:                pers = add (buffer, add (" ", pers));
                    627:                continue;
                    628: 
                    629:            default:
                    630:                return OK;
                    631:        }
                    632: }
                    633: 
                    634: /*  */
                    635: 
                    636: static int
                    637: route_addr(buffer)
                    638:        register char *buffer;
                    639: {
                    640:     register char   *pp = cp;
                    641: 
                    642:     if (my_lex (buffer) == LX_AT) {
                    643:        if (route (buffer) == NOTOK)
                    644:            return NOTOK;
                    645:     }
                    646:     else
                    647:        cp = pp;
                    648: 
                    649:     if (local_part (buffer) == NOTOK)
                    650:        return NOTOK;
                    651: 
                    652:     switch (last_lex) {
                    653:        case LX_AT:
                    654:            return domain (buffer);
                    655: 
                    656:        case LX_RBRK:           /* no host */
                    657:        case LX_COMA:
                    658:        case LX_END:
                    659:            return OK;
                    660: 
                    661:        default:
                    662:            (void) sprintf (err, "no at-sign after local-part (%s)", buffer);
                    663:            return NOTOK;
                    664:     }
                    665: }
                    666: 
                    667: /*  */
                    668: 
                    669: static int
                    670: local_part(buffer)
                    671:        register char *buffer;
                    672: {
                    673:     ingrp = glevel;
                    674: 
                    675:     for (;;) {
                    676:        switch (my_lex (buffer)) {
                    677:            case LX_ATOM:
                    678:            case LX_QSTR:
                    679:                mbox = add (buffer, mbox);
                    680:                break;
                    681: 
                    682:            default:
                    683:                (void) sprintf (err, "no mailbox in local-part (%s)", buffer);
                    684:                return NOTOK;
                    685:        }
                    686: 
                    687:        switch (my_lex (buffer)) {
                    688:            case LX_DOT:
                    689:                mbox = add (buffer, mbox);
                    690:                continue;
                    691: 
                    692:            default:
                    693:                return OK;
                    694:        }
                    695:     }
                    696: }
                    697: 
                    698: /*  */
                    699: 
                    700: static int
                    701: domain(buffer)
                    702:        register char *buffer;
                    703: {
                    704:     for (;;) {
                    705:        switch (my_lex (buffer)) {
                    706:            case LX_ATOM:
                    707:            case LX_DLIT:
                    708:                host = add (buffer, host);
                    709:                break;
                    710: 
                    711:            default:
                    712:                (void) sprintf (err,
                    713:                        "no sub-domain in domain-part of address (%s)",
                    714:                        buffer);
                    715:                return NOTOK;
                    716:        }
                    717: 
                    718:        switch (my_lex (buffer)) {
                    719:            case LX_DOT:
                    720:                host = add (buffer, host);
                    721:                continue;
                    722: 
                    723:            case LX_AT:         /* sigh (0) */
                    724:                mbox = add (host, add ("%", mbox));
                    725:                free (host);
                    726:                host = NULL;
                    727:                continue;
                    728: 
                    729:            default:
                    730:                return OK;
                    731:        }
                    732:     }
                    733: }
                    734: 
                    735: /*  */
                    736: 
                    737: static int
                    738: route(buffer)
                    739:        register char *buffer;
                    740: {
                    741:     path = getcpy ("@");
                    742: 
                    743:     for (;;) {
                    744:        switch (my_lex (buffer)) {
                    745:            case LX_ATOM:
                    746:            case LX_DLIT:
                    747:                path = add (buffer, path);
                    748:                break;
                    749: 
                    750:            default:
                    751:                (void) sprintf (err,
                    752:                        "no sub-domain in domain-part of address (%s)",
                    753:                        buffer);
                    754:                return NOTOK;
                    755:        }
                    756:        switch (my_lex (buffer)) {
                    757:            case LX_COMA:
                    758:                path = add (buffer, path);
                    759:                for (;;) {
                    760:                    switch (my_lex (buffer)) {
                    761:                        case LX_COMA:
                    762:                            continue;
                    763: 
                    764:                        case LX_AT:
                    765:                            path = add (buffer, path);
                    766:                            break;
                    767: 
                    768:                        default:
                    769:                            (void) sprintf (err,
                    770:                                    "no at-sign found for next domain in route (%s)",
                    771:                            buffer);
                    772:                    }
                    773:                    break;
                    774:                }
                    775:                continue;
                    776: 
                    777:            case LX_AT:         /* XXX */
                    778:            case LX_DOT:
                    779:                path = add (buffer, path);
                    780:                continue;
                    781: 
                    782:            case LX_COLN:
                    783:                path = add (buffer, path);
                    784:                return OK;
                    785: 
                    786:            default:
                    787:                (void) sprintf (err,
                    788:                        "no colon found to terminate route (%s)", buffer);
                    789:                return NOTOK;
                    790:        }
                    791:     }
                    792: }
                    793: 
                    794: /*  */
                    795: 
                    796: static int
                    797: my_lex(buffer)
                    798:        register char *buffer;
                    799: {
                    800:     int     i;
                    801:     register char    c,
                    802:                    *bp;
                    803: 
                    804:     bp = buffer;
                    805:     *bp = NULL;
                    806:     if (!cp)
                    807:        return (last_lex = LX_END);
                    808: 
                    809:     c = *cp++;
                    810:     while (isspace (c))
                    811:        c = *cp++;
                    812:     if (c == NULL) {
                    813:        cp = NULL;
                    814:        return (last_lex = LX_END);
                    815:     }
                    816: 
                    817:     if (c == '(')
                    818:        for (*bp++ = c, i = 0;;)
                    819:            switch (c = *cp++) {
                    820:                case NULL:
                    821:                    cp = NULL;
                    822:                    return (last_lex = LX_ERR);
                    823:                case QUOTE:
                    824:                    *bp++ = c;
                    825:                    if ((c = *cp++) == NULL) {
                    826:                        cp = NULL;
                    827:                        return (last_lex = LX_ERR);
                    828:                    }
                    829:                    *bp++ = c;
                    830:                    continue;
                    831:                case '(':
                    832:                    i++;
                    833:                default:
                    834:                    *bp++ = c;
                    835:                    continue;
                    836:                case ')':
                    837:                    *bp++ = c;
                    838:                    if (--i < 0) {
                    839:                        *bp = NULL;
                    840:                        note = note ? add (buffer, add (" ", note))
                    841:                            : getcpy (buffer);
                    842:                        return my_lex (buffer);
                    843:                    }
                    844:            }
                    845: 
                    846: /*  */
                    847: 
                    848:     if (c == '"')
                    849:        for (*bp++ = c;;)
                    850:            switch (c = *cp++) {
                    851:                case NULL:
                    852:                    cp = NULL;
                    853:                    return (last_lex = LX_ERR);
                    854:                case QUOTE:
                    855:                    *bp++ = c;
                    856:                    if ((c = *cp++) == NULL) {
                    857:                        cp = NULL;
                    858:                        return (last_lex = LX_ERR);
                    859:                    }
                    860:                default:
                    861:                    *bp++ = c;
                    862:                    continue;
                    863:                case '"':
                    864:                    *bp++ = c;
                    865:                    *bp = NULL;
                    866:                    return (last_lex = LX_QSTR);
                    867:            }
                    868: 
                    869:     if (c == '[')
                    870:        for (*bp++ = c;;)
                    871:            switch (c = *cp++) {
                    872:                case NULL:
                    873:                    cp = NULL;
                    874:                    return (last_lex = LX_ERR);
                    875:                case QUOTE:
                    876:                    *bp++ = c;
                    877:                    if ((c = *cp++) == NULL) {
                    878:                        cp = NULL;
                    879:                        return (last_lex = LX_ERR);
                    880:                    }
                    881:                default:
                    882:                    *bp++ = c;
                    883:                    continue;
                    884:                case ']':
                    885:                    *bp++ = c;
                    886:                    *bp = NULL;
                    887:                    return (last_lex = LX_DLIT);
                    888:            }
                    889: 
                    890: /*  */
                    891: 
                    892:     *bp++ = c;
                    893:     *bp = NULL;
                    894:     for (i = 0; special[i].lx_chr != NULL; i++)
                    895:        if (c == special[i].lx_chr)
                    896:            return (last_lex = special[i].lx_val);
                    897: 
                    898:     if (iscntrl (c))
                    899:        return (last_lex = LX_ERR);
                    900: 
                    901:     for (;;) {
                    902:        if ((c = *cp++) == NULL)
                    903:            break;
                    904:        for (i = 0; special[i].lx_chr != NULL; i++)
                    905:            if (c == special[i].lx_chr)
                    906:                goto got_atom;
                    907:        if (iscntrl (c) || isspace (c))
                    908:            break;
                    909:        *bp++ = c;
                    910:     }
                    911: got_atom: ;
                    912:     if (c == NULL)
                    913:        cp = NULL;
                    914:     else
                    915:        cp--;
                    916:     *bp = NULL;
                    917:     last_lex = !lequal (buffer, "at") || cp == NULL || index (cp, '<') != NULL
                    918:        ? LX_ATOM : LX_AT;
                    919:     return last_lex;
                    920: }
                    921: 
                    922: /*  */
                    923: 
                    924: char *
                    925: legal_person(p)
                    926:        register char *p;
                    927: {
                    928:     int     i;
                    929:     register char   *cp;
                    930:     static char buffer[BUFSIZ];
                    931: 
                    932:     if (*p == '"')
                    933:        return p;
                    934:     for (cp = p; *cp; cp++)
                    935:        for (i = 0; special[i].lx_chr; i++)
                    936:            if (*cp == special[i].lx_chr) {
                    937:                (void) sprintf (buffer, "\"%s\"", p);
                    938:                return buffer;
                    939:            }
                    940: 
                    941:     return p;
                    942: }
                    943: 
                    944: /*  */
                    945: 
                    946: mfgets(in, bp)
                    947:        register FILE *in;
                    948:        register char **bp;
                    949: {
                    950:     int     i;
                    951:     register char   *cp,
                    952:                    *dp,
                    953:                    *ep;
                    954:     static int  len = 0;
                    955:     static char *pp = NULL;
                    956: 
                    957:     if (pp == NULL)
                    958:        if ((pp = malloc ((unsigned) (len = BUFSIZ))) == NULL)
                    959:            return NOTOK;
                    960: 
                    961:     for (ep = (cp = pp) + len - 2;;) {
                    962:        switch (i = getc (in)) {
                    963:            case EOF:
                    964:        eol:    ;
                    965:                if (cp != pp) {
                    966:                    *cp = NULL;
                    967:                    *bp = pp;
                    968:                    return OK;
                    969:                }
                    970:        eoh:    ;
                    971:                *bp = NULL;
                    972:                free (pp);
                    973:                pp = NULL;
                    974:                return DONE;
                    975: 
                    976:            case NULL:
                    977:                continue;
                    978: 
                    979:            case '\n':
                    980:                if (cp == pp)   /* end of headers, gobble it */
                    981:                    goto eoh;
                    982:                switch (i = getc (in)) {
                    983:                    default:    /* end of line */
                    984:                    case '\n':  /* end of headers, save for next call */
                    985:                        (void) ungetc (i, in);
                    986:                        goto eol;
                    987: 
                    988:                    case ' ':   /* continue headers */
                    989:                    case '\t':
                    990:                        *cp++ = '\n';
                    991:                        break;
                    992:                }               /* fall into default case */
                    993: 
                    994:            default:
                    995:                *cp++ = i;
                    996:                break;
                    997:        }
                    998:        if (cp >= ep)
                    999:            if ((dp = realloc (pp, (unsigned) (len += BUFSIZ))) == NULL) {
                   1000:                free (pp);
                   1001:                pp = NULL;
                   1002:                return NOTOK;
                   1003:            }
                   1004:            else
                   1005:                cp += dp - pp, ep = (pp = cp) + len - 2;
                   1006:     }
                   1007: }

unix.superglobalmegacorp.com

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