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

unix.superglobalmegacorp.com

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