Annotation of 43BSDReno/contrib/mh/zotnet/mf/mf.c, revision 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.