Annotation of 43BSDTahoe/usr.lib/sendmail/src/parseaddr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Eric P. Allman
                      3:  * Copyright (c) 1988 Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms are permitted
                      7:  * provided that the above copyright notice and this paragraph are
                      8:  * duplicated in all such forms and that any documentation,
                      9:  * advertising materials, and other materials related to such
                     10:  * distribution and use acknowledge that the software was developed
                     11:  * by the University of California, Berkeley.  The name of the
                     12:  * University may not be used to endorse or promote products derived
                     13:  * from this software without specific prior written permission.
                     14:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     15:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     16:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char sccsid[] = "@(#)parseaddr.c        5.9 (Berkeley) 6/30/88";
                     21: #endif /* not lint */
                     22: 
                     23: # include "sendmail.h"
                     24: 
                     25: /*
                     26: **  PARSEADDR -- Parse an address
                     27: **
                     28: **     Parses an address and breaks it up into three parts: a
                     29: **     net to transmit the message on, the host to transmit it
                     30: **     to, and a user on that host.  These are loaded into an
                     31: **     ADDRESS header with the values squirreled away if necessary.
                     32: **     The "user" part may not be a real user; the process may
                     33: **     just reoccur on that machine.  For example, on a machine
                     34: **     with an arpanet connection, the address
                     35: **             csvax.bill@berkeley
                     36: **     will break up to a "user" of 'csvax.bill' and a host
                     37: **     of 'berkeley' -- to be transmitted over the arpanet.
                     38: **
                     39: **     Parameters:
                     40: **             addr -- the address to parse.
                     41: **             a -- a pointer to the address descriptor buffer.
                     42: **                     If NULL, a header will be created.
                     43: **             copyf -- determines what shall be copied:
                     44: **                     -1 -- don't copy anything.  The printname
                     45: **                             (q_paddr) is just addr, and the
                     46: **                             user & host are allocated internally
                     47: **                             to parse.
                     48: **                     0 -- copy out the parsed user & host, but
                     49: **                             don't copy the printname.
                     50: **                     +1 -- copy everything.
                     51: **             delim -- the character to terminate the address, passed
                     52: **                     to prescan.
                     53: **
                     54: **     Returns:
                     55: **             A pointer to the address descriptor header (`a' if
                     56: **                     `a' is non-NULL).
                     57: **             NULL on error.
                     58: **
                     59: **     Side Effects:
                     60: **             none
                     61: */
                     62: 
                     63: /* following delimiters are inherent to the internal algorithms */
                     64: # define DELIMCHARS    "\001()<>,;\\\"\r\n"    /* word delimiters */
                     65: 
                     66: ADDRESS *
                     67: parseaddr(addr, a, copyf, delim)
                     68:        char *addr;
                     69:        register ADDRESS *a;
                     70:        int copyf;
                     71:        char delim;
                     72: {
                     73:        register char **pvp;
                     74:        register struct mailer *m;
                     75:        char pvpbuf[PSBUFSIZE];
                     76:        extern char **prescan();
                     77:        extern ADDRESS *buildaddr();
                     78: 
                     79:        /*
                     80:        **  Initialize and prescan address.
                     81:        */
                     82: 
                     83:        CurEnv->e_to = addr;
                     84: # ifdef DEBUG
                     85:        if (tTd(20, 1))
                     86:                printf("\n--parseaddr(%s)\n", addr);
                     87: # endif DEBUG
                     88: 
                     89:        pvp = prescan(addr, delim, pvpbuf);
                     90:        if (pvp == NULL)
                     91:                return (NULL);
                     92: 
                     93:        /*
                     94:        **  Apply rewriting rules.
                     95:        **      Ruleset 0 does basic parsing.  It must resolve.
                     96:        */
                     97: 
                     98:        rewrite(pvp, 3);
                     99:        rewrite(pvp, 0);
                    100: 
                    101:        /*
                    102:        **  See if we resolved to a real mailer.
                    103:        */
                    104: 
                    105:        if (pvp[0][0] != CANONNET)
                    106:        {
                    107:                setstat(EX_USAGE);
                    108:                usrerr("cannot resolve name");
                    109:                return (NULL);
                    110:        }
                    111: 
                    112:        /*
                    113:        **  Build canonical address from pvp.
                    114:        */
                    115: 
                    116:        a = buildaddr(pvp, a);
                    117:        if (a == NULL)
                    118:                return (NULL);
                    119:        m = a->q_mailer;
                    120: 
                    121:        /*
                    122:        **  Make local copies of the host & user and then
                    123:        **  transport them out.
                    124:        */
                    125: 
                    126:        if (copyf > 0)
                    127:        {
                    128:                extern char *DelimChar;
                    129:                char savec = *DelimChar;
                    130: 
                    131:                *DelimChar = '\0';
                    132:                a->q_paddr = newstr(addr);
                    133:                *DelimChar = savec;
                    134:        }
                    135:        else
                    136:                a->q_paddr = addr;
                    137: 
                    138:        if (a->q_user == NULL)
                    139:                a->q_user = "";
                    140:        if (a->q_host == NULL)
                    141:                a->q_host = "";
                    142: 
                    143:        if (copyf >= 0)
                    144:        {
                    145:                a->q_host = newstr(a->q_host);
                    146:                if (a->q_user != a->q_paddr)
                    147:                        a->q_user = newstr(a->q_user);
                    148:        }
                    149: 
                    150:        /*
                    151:        **  Convert host name to lower case if requested.
                    152:        **      User name will be done later.
                    153:        */
                    154: 
                    155:        if (!bitnset(M_HST_UPPER, m->m_flags))
                    156:                makelower(a->q_host);
                    157: 
                    158:        /*
                    159:        **  Compute return value.
                    160:        */
                    161: 
                    162: # ifdef DEBUG
                    163:        if (tTd(20, 1))
                    164:        {
                    165:                printf("parseaddr-->");
                    166:                printaddr(a, FALSE);
                    167:        }
                    168: # endif DEBUG
                    169: 
                    170:        return (a);
                    171: }
                    172: /*
                    173: **  LOWERADDR -- map UPPER->lower case on addresses as requested.
                    174: **
                    175: **     Parameters:
                    176: **             a -- address to be mapped.
                    177: **
                    178: **     Returns:
                    179: **             none.
                    180: **
                    181: **     Side Effects:
                    182: **             none.
                    183: */
                    184: 
                    185: loweraddr(a)
                    186:        register ADDRESS *a;
                    187: {
                    188:        register MAILER *m = a->q_mailer;
                    189: 
                    190:        if (!bitnset(M_USR_UPPER, m->m_flags))
                    191:                makelower(a->q_user);
                    192: }
                    193: /*
                    194: **  PRESCAN -- Prescan name and make it canonical
                    195: **
                    196: **     Scans a name and turns it into a set of tokens.  This process
                    197: **     deletes blanks and comments (in parentheses).
                    198: **
                    199: **     This routine knows about quoted strings and angle brackets.
                    200: **
                    201: **     There are certain subtleties to this routine.  The one that
                    202: **     comes to mind now is that backslashes on the ends of names
                    203: **     are silently stripped off; this is intentional.  The problem
                    204: **     is that some versions of sndmsg (like at LBL) set the kill
                    205: **     character to something other than @ when reading addresses;
                    206: **     so people type "csvax.eric\@berkeley" -- which screws up the
                    207: **     berknet mailer.
                    208: **
                    209: **     Parameters:
                    210: **             addr -- the name to chomp.
                    211: **             delim -- the delimiter for the address, normally
                    212: **                     '\0' or ','; \0 is accepted in any case.
                    213: **                     If '\t' then we are reading the .cf file.
                    214: **             pvpbuf -- place to put the saved text -- note that
                    215: **                     the pointers are static.
                    216: **
                    217: **     Returns:
                    218: **             A pointer to a vector of tokens.
                    219: **             NULL on error.
                    220: **
                    221: **     Side Effects:
                    222: **             sets DelimChar to point to the character matching 'delim'.
                    223: */
                    224: 
                    225: /* states and character types */
                    226: # define OPR           0       /* operator */
                    227: # define ATM           1       /* atom */
                    228: # define QST           2       /* in quoted string */
                    229: # define SPC           3       /* chewing up spaces */
                    230: # define ONE           4       /* pick up one character */
                    231: 
                    232: # define NSTATES       5       /* number of states */
                    233: # define TYPE          017     /* mask to select state type */
                    234: 
                    235: /* meta bits for table */
                    236: # define M             020     /* meta character; don't pass through */
                    237: # define B             040     /* cause a break */
                    238: # define MB            M|B     /* meta-break */
                    239: 
                    240: static short StateTab[NSTATES][NSTATES] =
                    241: {
                    242:    /*  oldst   chtype> OPR     ATM     QST     SPC     ONE     */
                    243:        /*OPR*/         OPR|B,  ATM|B,  QST|B,  SPC|MB, ONE|B,
                    244:        /*ATM*/         OPR|B,  ATM,    QST|B,  SPC|MB, ONE|B,
                    245:        /*QST*/         QST,    QST,    OPR,    QST,    QST,
                    246:        /*SPC*/         OPR,    ATM,    QST,    SPC|M,  ONE,
                    247:        /*ONE*/         OPR,    OPR,    OPR,    OPR,    OPR,
                    248: };
                    249: 
                    250: # define NOCHAR                -1      /* signal nothing in lookahead token */
                    251: 
                    252: char   *DelimChar;             /* set to point to the delimiter */
                    253: 
                    254: char **
                    255: prescan(addr, delim, pvpbuf)
                    256:        char *addr;
                    257:        char delim;
                    258:        char pvpbuf[];
                    259: {
                    260:        register char *p;
                    261:        register char *q;
                    262:        register int c;
                    263:        char **avp;
                    264:        bool bslashmode;
                    265:        int cmntcnt;
                    266:        int anglecnt;
                    267:        char *tok;
                    268:        int state;
                    269:        int newstate;
                    270:        static char *av[MAXATOM+1];
                    271:        extern int errno;
                    272: 
                    273:        /* make sure error messages don't have garbage on them */
                    274:        errno = 0;
                    275: 
                    276:        q = pvpbuf;
                    277:        bslashmode = FALSE;
                    278:        cmntcnt = 0;
                    279:        anglecnt = 0;
                    280:        avp = av;
                    281:        state = OPR;
                    282:        c = NOCHAR;
                    283:        p = addr;
                    284: # ifdef DEBUG
                    285:        if (tTd(22, 45))
                    286:        {
                    287:                printf("prescan: ");
                    288:                xputs(p);
                    289:                (void) putchar('\n');
                    290:        }
                    291: # endif DEBUG
                    292: 
                    293:        do
                    294:        {
                    295:                /* read a token */
                    296:                tok = q;
                    297:                for (;;)
                    298:                {
                    299:                        /* store away any old lookahead character */
                    300:                        if (c != NOCHAR)
                    301:                        {
                    302:                                /* see if there is room */
                    303:                                if (q >= &pvpbuf[PSBUFSIZE - 5])
                    304:                                {
                    305:                                        usrerr("Address too long");
                    306:                                        DelimChar = p;
                    307:                                        return (NULL);
                    308:                                }
                    309: 
                    310:                                /* squirrel it away */
                    311:                                *q++ = c;
                    312:                        }
                    313: 
                    314:                        /* read a new input character */
                    315:                        c = *p++;
                    316:                        if (c == '\0')
                    317:                                break;
                    318:                        c &= ~0200;
                    319: 
                    320: # ifdef DEBUG
                    321:                        if (tTd(22, 101))
                    322:                                printf("c=%c, s=%d; ", c, state);
                    323: # endif DEBUG
                    324: 
                    325:                        /* chew up special characters */
                    326:                        *q = '\0';
                    327:                        if (bslashmode)
                    328:                        {
                    329:                                /* kludge \! for naive users */
                    330:                                if (c != '!')
                    331:                                        c |= 0200;
                    332:                                bslashmode = FALSE;
                    333:                        }
                    334:                        else if (c == '\\')
                    335:                        {
                    336:                                bslashmode = TRUE;
                    337:                                c = NOCHAR;
                    338:                        }
                    339:                        else if (state == QST)
                    340:                        {
                    341:                                /* do nothing, just avoid next clauses */
                    342:                        }
                    343:                        else if (c == '(')
                    344:                        {
                    345:                                cmntcnt++;
                    346:                                c = NOCHAR;
                    347:                        }
                    348:                        else if (c == ')')
                    349:                        {
                    350:                                if (cmntcnt <= 0)
                    351:                                {
                    352:                                        usrerr("Unbalanced ')'");
                    353:                                        DelimChar = p;
                    354:                                        return (NULL);
                    355:                                }
                    356:                                else
                    357:                                        cmntcnt--;
                    358:                        }
                    359:                        else if (cmntcnt > 0)
                    360:                                c = NOCHAR;
                    361:                        else if (c == '<')
                    362:                                anglecnt++;
                    363:                        else if (c == '>')
                    364:                        {
                    365:                                if (anglecnt <= 0)
                    366:                                {
                    367:                                        usrerr("Unbalanced '>'");
                    368:                                        DelimChar = p;
                    369:                                        return (NULL);
                    370:                                }
                    371:                                anglecnt--;
                    372:                        }
                    373:                        else if (delim == ' ' && isspace(c))
                    374:                                c = ' ';
                    375: 
                    376:                        if (c == NOCHAR)
                    377:                                continue;
                    378: 
                    379:                        /* see if this is end of input */
                    380:                        if (c == delim && anglecnt <= 0 && state != QST)
                    381:                                break;
                    382: 
                    383:                        newstate = StateTab[state][toktype(c)];
                    384: # ifdef DEBUG
                    385:                        if (tTd(22, 101))
                    386:                                printf("ns=%02o\n", newstate);
                    387: # endif DEBUG
                    388:                        state = newstate & TYPE;
                    389:                        if (bitset(M, newstate))
                    390:                                c = NOCHAR;
                    391:                        if (bitset(B, newstate))
                    392:                                break;
                    393:                }
                    394: 
                    395:                /* new token */
                    396:                if (tok != q)
                    397:                {
                    398:                        *q++ = '\0';
                    399: # ifdef DEBUG
                    400:                        if (tTd(22, 36))
                    401:                        {
                    402:                                printf("tok=");
                    403:                                xputs(tok);
                    404:                                (void) putchar('\n');
                    405:                        }
                    406: # endif DEBUG
                    407:                        if (avp >= &av[MAXATOM])
                    408:                        {
                    409:                                syserr("prescan: too many tokens");
                    410:                                DelimChar = p;
                    411:                                return (NULL);
                    412:                        }
                    413:                        *avp++ = tok;
                    414:                }
                    415:        } while (c != '\0' && (c != delim || anglecnt > 0));
                    416:        *avp = NULL;
                    417:        DelimChar = --p;
                    418:        if (cmntcnt > 0)
                    419:                usrerr("Unbalanced '('");
                    420:        else if (anglecnt > 0)
                    421:                usrerr("Unbalanced '<'");
                    422:        else if (state == QST)
                    423:                usrerr("Unbalanced '\"'");
                    424:        else if (av[0] != NULL)
                    425:                return (av);
                    426:        return (NULL);
                    427: }
                    428: /*
                    429: **  TOKTYPE -- return token type
                    430: **
                    431: **     Parameters:
                    432: **             c -- the character in question.
                    433: **
                    434: **     Returns:
                    435: **             Its type.
                    436: **
                    437: **     Side Effects:
                    438: **             none.
                    439: */
                    440: 
                    441: toktype(c)
                    442:        register char c;
                    443: {
                    444:        static char buf[50];
                    445:        static bool firstime = TRUE;
                    446: 
                    447:        if (firstime)
                    448:        {
                    449:                firstime = FALSE;
                    450:                expand("\001o", buf, &buf[sizeof buf - 1], CurEnv);
                    451:                (void) strcat(buf, DELIMCHARS);
                    452:        }
                    453:        if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
                    454:                return (ONE);
                    455:        if (c == '"')
                    456:                return (QST);
                    457:        if (!isascii(c))
                    458:                return (ATM);
                    459:        if (isspace(c) || c == ')')
                    460:                return (SPC);
                    461:        if (iscntrl(c) || index(buf, c) != NULL)
                    462:                return (OPR);
                    463:        return (ATM);
                    464: }
                    465: /*
                    466: **  REWRITE -- apply rewrite rules to token vector.
                    467: **
                    468: **     This routine is an ordered production system.  Each rewrite
                    469: **     rule has a LHS (called the pattern) and a RHS (called the
                    470: **     rewrite); 'rwr' points the the current rewrite rule.
                    471: **
                    472: **     For each rewrite rule, 'avp' points the address vector we
                    473: **     are trying to match against, and 'pvp' points to the pattern.
                    474: **     If pvp points to a special match value (MATCHZANY, MATCHANY,
                    475: **     MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp
                    476: **     matched is saved away in the match vector (pointed to by 'mvp').
                    477: **
                    478: **     When a match between avp & pvp does not match, we try to
                    479: **     back out.  If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS
                    480: **     we must also back out the match in mvp.  If we reach a
                    481: **     MATCHANY or MATCHZANY we just extend the match and start
                    482: **     over again.
                    483: **
                    484: **     When we finally match, we rewrite the address vector
                    485: **     and try over again.
                    486: **
                    487: **     Parameters:
                    488: **             pvp -- pointer to token vector.
                    489: **
                    490: **     Returns:
                    491: **             none.
                    492: **
                    493: **     Side Effects:
                    494: **             pvp is modified.
                    495: */
                    496: 
                    497: struct match
                    498: {
                    499:        char    **first;        /* first token matched */
                    500:        char    **last;         /* last token matched */
                    501: };
                    502: 
                    503: # define MAXMATCH      9       /* max params per rewrite */
                    504: 
                    505: 
                    506: rewrite(pvp, ruleset)
                    507:        char **pvp;
                    508:        int ruleset;
                    509: {
                    510:        register char *ap;              /* address pointer */
                    511:        register char *rp;              /* rewrite pointer */
                    512:        register char **avp;            /* address vector pointer */
                    513:        register char **rvp;            /* rewrite vector pointer */
                    514:        register struct match *mlp;     /* cur ptr into mlist */
                    515:        register struct rewrite *rwr;   /* pointer to current rewrite rule */
                    516:        struct match mlist[MAXMATCH];   /* stores match on LHS */
                    517:        char *npvp[MAXATOM+1];          /* temporary space for rebuild */
                    518: 
                    519:        if (OpMode == MD_TEST || tTd(21, 2))
                    520:        {
                    521:                printf("rewrite: ruleset %2d   input:", ruleset);
                    522:                printav(pvp);
                    523:        }
                    524:        if (pvp == NULL)
                    525:                return;
                    526: 
                    527:        /*
                    528:        **  Run through the list of rewrite rules, applying
                    529:        **      any that match.
                    530:        */
                    531: 
                    532:        for (rwr = RewriteRules[ruleset]; rwr != NULL; )
                    533:        {
                    534: # ifdef DEBUG
                    535:                if (tTd(21, 12))
                    536:                {
                    537:                        printf("-----trying rule:");
                    538:                        printav(rwr->r_lhs);
                    539:                }
                    540: # endif DEBUG
                    541: 
                    542:                /* try to match on this rule */
                    543:                mlp = mlist;
                    544:                rvp = rwr->r_lhs;
                    545:                avp = pvp;
                    546:                while ((ap = *avp) != NULL || *rvp != NULL)
                    547:                {
                    548:                        rp = *rvp;
                    549: # ifdef DEBUG
                    550:                        if (tTd(21, 35))
                    551:                        {
                    552:                                printf("ap=");
                    553:                                xputs(ap);
                    554:                                printf(", rp=");
                    555:                                xputs(rp);
                    556:                                printf("\n");
                    557:                        }
                    558: # endif DEBUG
                    559:                        if (rp == NULL)
                    560:                        {
                    561:                                /* end-of-pattern before end-of-address */
                    562:                                goto backup;
                    563:                        }
                    564:                        if (ap == NULL && *rp != MATCHZANY)
                    565:                        {
                    566:                                /* end-of-input */
                    567:                                break;
                    568:                        }
                    569: 
                    570:                        switch (*rp)
                    571:                        {
                    572:                                register STAB *s;
                    573: 
                    574:                          case MATCHCLASS:
                    575:                          case MATCHNCLASS:
                    576:                                /* match any token in (not in) a class */
                    577:                                s = stab(ap, ST_CLASS, ST_FIND);
                    578:                                if (s == NULL || !bitnset(rp[1], s->s_class))
                    579:                                {
                    580:                                        if (*rp == MATCHCLASS)
                    581:                                                goto backup;
                    582:                                }
                    583:                                else if (*rp == MATCHNCLASS)
                    584:                                        goto backup;
                    585: 
                    586:                                /* explicit fall-through */
                    587: 
                    588:                          case MATCHONE:
                    589:                          case MATCHANY:
                    590:                                /* match exactly one token */
                    591:                                mlp->first = avp;
                    592:                                mlp->last = avp++;
                    593:                                mlp++;
                    594:                                break;
                    595: 
                    596:                          case MATCHZANY:
                    597:                                /* match zero or more tokens */
                    598:                                mlp->first = avp;
                    599:                                mlp->last = avp - 1;
                    600:                                mlp++;
                    601:                                break;
                    602: 
                    603:                          default:
                    604:                                /* must have exact match */
                    605:                                if (strcasecmp(rp, ap))
                    606:                                        goto backup;
                    607:                                avp++;
                    608:                                break;
                    609:                        }
                    610: 
                    611:                        /* successful match on this token */
                    612:                        rvp++;
                    613:                        continue;
                    614: 
                    615:                  backup:
                    616:                        /* match failed -- back up */
                    617:                        while (--rvp >= rwr->r_lhs)
                    618:                        {
                    619:                                rp = *rvp;
                    620:                                if (*rp == MATCHANY || *rp == MATCHZANY)
                    621:                                {
                    622:                                        /* extend binding and continue */
                    623:                                        avp = ++mlp[-1].last;
                    624:                                        avp++;
                    625:                                        rvp++;
                    626:                                        break;
                    627:                                }
                    628:                                avp--;
                    629:                                if (*rp == MATCHONE || *rp == MATCHCLASS ||
                    630:                                    *rp == MATCHNCLASS)
                    631:                                {
                    632:                                        /* back out binding */
                    633:                                        mlp--;
                    634:                                }
                    635:                        }
                    636: 
                    637:                        if (rvp < rwr->r_lhs)
                    638:                        {
                    639:                                /* total failure to match */
                    640:                                break;
                    641:                        }
                    642:                }
                    643: 
                    644:                /*
                    645:                **  See if we successfully matched
                    646:                */
                    647: 
                    648:                if (rvp < rwr->r_lhs || *rvp != NULL)
                    649:                {
                    650: # ifdef DEBUG
                    651:                        if (tTd(21, 10))
                    652:                                printf("----- rule fails\n");
                    653: # endif DEBUG
                    654:                        rwr = rwr->r_next;
                    655:                        continue;
                    656:                }
                    657: 
                    658:                rvp = rwr->r_rhs;
                    659: # ifdef DEBUG
                    660:                if (tTd(21, 12))
                    661:                {
                    662:                        printf("-----rule matches:");
                    663:                        printav(rvp);
                    664:                }
                    665: # endif DEBUG
                    666: 
                    667:                rp = *rvp;
                    668:                if (*rp == CANONUSER)
                    669:                {
                    670:                        rvp++;
                    671:                        rwr = rwr->r_next;
                    672:                }
                    673:                else if (*rp == CANONHOST)
                    674:                {
                    675:                        rvp++;
                    676:                        rwr = NULL;
                    677:                }
                    678:                else if (*rp == CANONNET)
                    679:                        rwr = NULL;
                    680: 
                    681:                /* substitute */
                    682:                for (avp = npvp; *rvp != NULL; rvp++)
                    683:                {
                    684:                        register struct match *m;
                    685:                        register char **pp;
                    686: 
                    687:                        rp = *rvp;
                    688:                        if (*rp == MATCHREPL)
                    689:                        {
                    690:                                /* substitute from LHS */
                    691:                                m = &mlist[rp[1] - '1'];
                    692:                                if (m >= mlp)
                    693:                                {
                    694:                                        syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);
                    695:                                        return;
                    696:                                }
                    697: # ifdef DEBUG
                    698:                                if (tTd(21, 15))
                    699:                                {
                    700:                                        printf("$%c:", rp[1]);
                    701:                                        pp = m->first;
                    702:                                        while (pp <= m->last)
                    703:                                        {
                    704:                                                printf(" %x=\"", *pp);
                    705:                                                (void) fflush(stdout);
                    706:                                                printf("%s\"", *pp++);
                    707:                                        }
                    708:                                        printf("\n");
                    709:                                }
                    710: # endif DEBUG
                    711:                                pp = m->first;
                    712:                                while (pp <= m->last)
                    713:                                {
                    714:                                        if (avp >= &npvp[MAXATOM])
                    715:                                        {
                    716:                                                syserr("rewrite: expansion too long");
                    717:                                                return;
                    718:                                        }
                    719:                                        *avp++ = *pp++;
                    720:                                }
                    721:                        }
                    722:                        else
                    723:                        {
                    724:                                /* vanilla replacement */
                    725:                                if (avp >= &npvp[MAXATOM])
                    726:                                {
                    727:        toolong:
                    728:                                        syserr("rewrite: expansion too long");
                    729:                                        return;
                    730:                                }
                    731:                                *avp++ = rp;
                    732:                        }
                    733:                }
                    734:                *avp++ = NULL;
                    735: 
                    736:                /*
                    737:                **  Check for any hostname lookups.
                    738:                */
                    739: 
                    740:                for (rvp = npvp; *rvp != NULL; rvp++)
                    741:                {
                    742:                        char **hbrvp;
                    743:                        char **xpvp;
                    744:                        int trsize;
                    745:                        char *olddelimchar;
                    746:                        char buf[MAXNAME + 1];
                    747:                        char *pvpb1[MAXATOM + 1];
                    748:                        char pvpbuf[PSBUFSIZE];
                    749:                        extern char *DelimChar;
                    750: 
                    751:                        if (**rvp != HOSTBEGIN)
                    752:                                continue;
                    753: 
                    754:                        /*
                    755:                        **  Got a hostname lookup.
                    756:                        **
                    757:                        **      This could be optimized fairly easily.
                    758:                        */
                    759: 
                    760:                        hbrvp = rvp;
                    761: 
                    762:                        /* extract the match part */
                    763:                        while (*++rvp != NULL && **rvp != HOSTEND)
                    764:                                continue;
                    765:                        if (*rvp != NULL)
                    766:                                *rvp++ = NULL;
                    767: 
                    768:                        /* save the remainder of the input string */
                    769:                        trsize = (int) (avp - rvp + 1) * sizeof *rvp;
                    770:                        bcopy((char *) rvp, (char *) pvpb1, trsize);
                    771: 
                    772:                        /* look it up */
                    773:                        cataddr(++hbrvp, buf, sizeof buf);
                    774:                        maphostname(buf, sizeof buf);
                    775: 
                    776:                        /* scan the new host name */
                    777:                        olddelimchar = DelimChar;
                    778:                        xpvp = prescan(buf, '\0', pvpbuf);
                    779:                        DelimChar = olddelimchar;
                    780:                        if (xpvp == NULL)
                    781:                        {
                    782:                                syserr("rewrite: cannot prescan canonical hostname: %s", buf);
                    783:                                return;
                    784:                        }
                    785: 
                    786:                        /* append it to the token list */
                    787:                        for (avp = --hbrvp; *xpvp != NULL; xpvp++)
                    788:                        {
                    789:                                *avp++ = newstr(*xpvp);
                    790:                                if (avp >= &npvp[MAXATOM])
                    791:                                        goto toolong;
                    792:                        }
                    793: 
                    794:                        /* restore the old trailing information */
                    795:                        for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
                    796:                                if (avp >= &npvp[MAXATOM])
                    797:                                        goto toolong;
                    798: 
                    799:                        break;
                    800:                }
                    801: 
                    802:                /*
                    803:                **  Check for subroutine calls.
                    804:                */
                    805: 
                    806:                if (*npvp != NULL && **npvp == CALLSUBR)
                    807:                {
                    808:                        bcopy((char *) &npvp[2], (char *) pvp,
                    809:                                (int) (avp - npvp - 2) * sizeof *avp);
                    810: # ifdef DEBUG
                    811:                        if (tTd(21, 3))
                    812:                                printf("-----callsubr %s\n", npvp[1]);
                    813: # endif DEBUG
                    814:                        rewrite(pvp, atoi(npvp[1]));
                    815:                }
                    816:                else
                    817:                {
                    818:                        bcopy((char *) npvp, (char *) pvp,
                    819:                                (int) (avp - npvp) * sizeof *avp);
                    820:                }
                    821: # ifdef DEBUG
                    822:                if (tTd(21, 4))
                    823:                {
                    824:                        printf("rewritten as:");
                    825:                        printav(pvp);
                    826:                }
                    827: # endif DEBUG
                    828:        }
                    829: 
                    830:        if (OpMode == MD_TEST || tTd(21, 2))
                    831:        {
                    832:                printf("rewrite: ruleset %2d returns:", ruleset);
                    833:                printav(pvp);
                    834:        }
                    835: }
                    836: /*
                    837: **  BUILDADDR -- build address from token vector.
                    838: **
                    839: **     Parameters:
                    840: **             tv -- token vector.
                    841: **             a -- pointer to address descriptor to fill.
                    842: **                     If NULL, one will be allocated.
                    843: **
                    844: **     Returns:
                    845: **             NULL if there was an error.
                    846: **             'a' otherwise.
                    847: **
                    848: **     Side Effects:
                    849: **             fills in 'a'
                    850: */
                    851: 
                    852: ADDRESS *
                    853: buildaddr(tv, a)
                    854:        register char **tv;
                    855:        register ADDRESS *a;
                    856: {
                    857:        static char buf[MAXNAME];
                    858:        struct mailer **mp;
                    859:        register struct mailer *m;
                    860: 
                    861:        if (a == NULL)
                    862:                a = (ADDRESS *) xalloc(sizeof *a);
                    863:        bzero((char *) a, sizeof *a);
                    864: 
                    865:        /* figure out what net/mailer to use */
                    866:        if (**tv != CANONNET)
                    867:        {
                    868:                syserr("buildaddr: no net");
                    869:                return (NULL);
                    870:        }
                    871:        tv++;
                    872:        if (!strcasecmp(*tv, "error"))
                    873:        {
                    874:                if (**++tv == CANONHOST)
                    875:                {
                    876:                        setstat(atoi(*++tv));
                    877:                        tv++;
                    878:                }
                    879:                if (**tv != CANONUSER)
                    880:                        syserr("buildaddr: error: no user");
                    881:                buf[0] = '\0';
                    882:                while (*++tv != NULL)
                    883:                {
                    884:                        if (buf[0] != '\0')
                    885:                                (void) strcat(buf, " ");
                    886:                        (void) strcat(buf, *tv);
                    887:                }
                    888:                usrerr(buf);
                    889:                return (NULL);
                    890:        }
                    891:        for (mp = Mailer; (m = *mp++) != NULL; )
                    892:        {
                    893:                if (!strcasecmp(m->m_name, *tv))
                    894:                        break;
                    895:        }
                    896:        if (m == NULL)
                    897:        {
                    898:                syserr("buildaddr: unknown mailer %s", *tv);
                    899:                return (NULL);
                    900:        }
                    901:        a->q_mailer = m;
                    902: 
                    903:        /* figure out what host (if any) */
                    904:        tv++;
                    905:        if (!bitnset(M_LOCAL, m->m_flags))
                    906:        {
                    907:                if (**tv++ != CANONHOST)
                    908:                {
                    909:                        syserr("buildaddr: no host");
                    910:                        return (NULL);
                    911:                }
                    912:                buf[0] = '\0';
                    913:                while (*tv != NULL && **tv != CANONUSER)
                    914:                        (void) strcat(buf, *tv++);
                    915:                a->q_host = newstr(buf);
                    916:        }
                    917:        else
                    918:                a->q_host = NULL;
                    919: 
                    920:        /* figure out the user */
                    921:        if (**tv != CANONUSER)
                    922:        {
                    923:                syserr("buildaddr: no user");
                    924:                return (NULL);
                    925:        }
                    926: 
                    927:        /* rewrite according recipient mailer rewriting rules */
                    928:        rewrite(++tv, 2);
                    929:        if (m->m_r_rwset > 0)
                    930:                rewrite(tv, m->m_r_rwset);
                    931:        rewrite(tv, 4);
                    932: 
                    933:        /* save the result for the command line/RCPT argument */
                    934:        cataddr(tv, buf, sizeof buf);
                    935:        a->q_user = buf;
                    936: 
                    937:        return (a);
                    938: }
                    939: /*
                    940: **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
                    941: **
                    942: **     Parameters:
                    943: **             pvp -- parameter vector to rebuild.
                    944: **             buf -- buffer to build the string into.
                    945: **             sz -- size of buf.
                    946: **
                    947: **     Returns:
                    948: **             none.
                    949: **
                    950: **     Side Effects:
                    951: **             Destroys buf.
                    952: */
                    953: 
                    954: cataddr(pvp, buf, sz)
                    955:        char **pvp;
                    956:        char *buf;
                    957:        register int sz;
                    958: {
                    959:        bool oatomtok = FALSE;
                    960:        bool natomtok = FALSE;
                    961:        register int i;
                    962:        register char *p;
                    963: 
                    964:        if (pvp == NULL)
                    965:        {
                    966:                (void) strcpy(buf, "");
                    967:                return;
                    968:        }
                    969:        p = buf;
                    970:        sz -= 2;
                    971:        while (*pvp != NULL && (i = strlen(*pvp)) < sz)
                    972:        {
                    973:                natomtok = (toktype(**pvp) == ATM);
                    974:                if (oatomtok && natomtok)
                    975:                        *p++ = SpaceSub;
                    976:                (void) strcpy(p, *pvp);
                    977:                oatomtok = natomtok;
                    978:                p += i;
                    979:                sz -= i + 1;
                    980:                pvp++;
                    981:        }
                    982:        *p = '\0';
                    983: }
                    984: /*
                    985: **  SAMEADDR -- Determine if two addresses are the same
                    986: **
                    987: **     This is not just a straight comparison -- if the mailer doesn't
                    988: **     care about the host we just ignore it, etc.
                    989: **
                    990: **     Parameters:
                    991: **             a, b -- pointers to the internal forms to compare.
                    992: **
                    993: **     Returns:
                    994: **             TRUE -- they represent the same mailbox.
                    995: **             FALSE -- they don't.
                    996: **
                    997: **     Side Effects:
                    998: **             none.
                    999: */
                   1000: 
                   1001: bool
                   1002: sameaddr(a, b)
                   1003:        register ADDRESS *a;
                   1004:        register ADDRESS *b;
                   1005: {
                   1006:        /* if they don't have the same mailer, forget it */
                   1007:        if (a->q_mailer != b->q_mailer)
                   1008:                return (FALSE);
                   1009: 
                   1010:        /* if the user isn't the same, we can drop out */
                   1011:        if (strcmp(a->q_user, b->q_user) != 0)
                   1012:                return (FALSE);
                   1013: 
                   1014:        /* if the mailer ignores hosts, we have succeeded! */
                   1015:        if (bitnset(M_LOCAL, a->q_mailer->m_flags))
                   1016:                return (TRUE);
                   1017: 
                   1018:        /* otherwise compare hosts (but be careful for NULL ptrs) */
                   1019:        if (a->q_host == NULL || b->q_host == NULL)
                   1020:                return (FALSE);
                   1021:        if (strcmp(a->q_host, b->q_host) != 0)
                   1022:                return (FALSE);
                   1023: 
                   1024:        return (TRUE);
                   1025: }
                   1026: /*
                   1027: **  PRINTADDR -- print address (for debugging)
                   1028: **
                   1029: **     Parameters:
                   1030: **             a -- the address to print
                   1031: **             follow -- follow the q_next chain.
                   1032: **
                   1033: **     Returns:
                   1034: **             none.
                   1035: **
                   1036: **     Side Effects:
                   1037: **             none.
                   1038: */
                   1039: 
                   1040: # ifdef DEBUG
                   1041: 
                   1042: printaddr(a, follow)
                   1043:        register ADDRESS *a;
                   1044:        bool follow;
                   1045: {
                   1046:        bool first = TRUE;
                   1047: 
                   1048:        while (a != NULL)
                   1049:        {
                   1050:                first = FALSE;
                   1051:                printf("%x=", a);
                   1052:                (void) fflush(stdout);
                   1053:                printf("%s: mailer %d (%s), host `%s', user `%s'\n", a->q_paddr,
                   1054:                       a->q_mailer->m_mno, a->q_mailer->m_name, a->q_host,
                   1055:                       a->q_user);
                   1056:                printf("\tnext=%x, flags=%o, alias %x\n", a->q_next, a->q_flags,
                   1057:                       a->q_alias);
                   1058:                printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home,
                   1059:                       a->q_fullname);
                   1060: 
                   1061:                if (!follow)
                   1062:                        return;
                   1063:                a = a->q_next;
                   1064:        }
                   1065:        if (first)
                   1066:                printf("[NULL]\n");
                   1067: }
                   1068: 
                   1069: # endif DEBUG
                   1070: /*
                   1071: **  REMOTENAME -- return the name relative to the current mailer
                   1072: **
                   1073: **     Parameters:
                   1074: **             name -- the name to translate.
                   1075: **             m -- the mailer that we want to do rewriting relative
                   1076: **                     to.
                   1077: **             senderaddress -- if set, uses the sender rewriting rules
                   1078: **                     rather than the recipient rewriting rules.
                   1079: **             canonical -- if set, strip out any comment information,
                   1080: **                     etc.
                   1081: **
                   1082: **     Returns:
                   1083: **             the text string representing this address relative to
                   1084: **                     the receiving mailer.
                   1085: **
                   1086: **     Side Effects:
                   1087: **             none.
                   1088: **
                   1089: **     Warnings:
                   1090: **             The text string returned is tucked away locally;
                   1091: **                     copy it if you intend to save it.
                   1092: */
                   1093: 
                   1094: char *
                   1095: remotename(name, m, senderaddress, canonical)
                   1096:        char *name;
                   1097:        struct mailer *m;
                   1098:        bool senderaddress;
                   1099:        bool canonical;
                   1100: {
                   1101:        register char **pvp;
                   1102:        char *fancy;
                   1103:        extern char *macvalue();
                   1104:        char *oldg = macvalue('g', CurEnv);
                   1105:        static char buf[MAXNAME];
                   1106:        char lbuf[MAXNAME];
                   1107:        char pvpbuf[PSBUFSIZE];
                   1108:        extern char **prescan();
                   1109:        extern char *crackaddr();
                   1110: 
                   1111: # ifdef DEBUG
                   1112:        if (tTd(12, 1))
                   1113:                printf("remotename(%s)\n", name);
                   1114: # endif DEBUG
                   1115: 
                   1116:        /* don't do anything if we are tagging it as special */
                   1117:        if ((senderaddress ? m->m_s_rwset : m->m_r_rwset) < 0)
                   1118:                return (name);
                   1119: 
                   1120:        /*
                   1121:        **  Do a heuristic crack of this name to extract any comment info.
                   1122:        **      This will leave the name as a comment and a $g macro.
                   1123:        */
                   1124: 
                   1125:        if (canonical)
                   1126:                fancy = "\001g";
                   1127:        else
                   1128:                fancy = crackaddr(name);
                   1129: 
                   1130:        /*
                   1131:        **  Turn the name into canonical form.
                   1132:        **      Normally this will be RFC 822 style, i.e., "user@domain".
                   1133:        **      If this only resolves to "user", and the "C" flag is
                   1134:        **      specified in the sending mailer, then the sender's
                   1135:        **      domain will be appended.
                   1136:        */
                   1137: 
                   1138:        pvp = prescan(name, '\0', pvpbuf);
                   1139:        if (pvp == NULL)
                   1140:                return (name);
                   1141:        rewrite(pvp, 3);
                   1142:        if (CurEnv->e_fromdomain != NULL)
                   1143:        {
                   1144:                /* append from domain to this address */
                   1145:                register char **pxp = pvp;
                   1146: 
                   1147:                /* see if there is an "@domain" in the current name */
                   1148:                while (*pxp != NULL && strcmp(*pxp, "@") != 0)
                   1149:                        pxp++;
                   1150:                if (*pxp == NULL)
                   1151:                {
                   1152:                        /* no.... append the "@domain" from the sender */
                   1153:                        register char **qxq = CurEnv->e_fromdomain;
                   1154: 
                   1155:                        while ((*pxp++ = *qxq++) != NULL)
                   1156:                                continue;
                   1157:                        rewrite(pvp, 3);
                   1158:                }
                   1159:        }
                   1160: 
                   1161:        /*
                   1162:        **  Do more specific rewriting.
                   1163:        **      Rewrite using ruleset 1 or 2 depending on whether this is
                   1164:        **              a sender address or not.
                   1165:        **      Then run it through any receiving-mailer-specific rulesets.
                   1166:        */
                   1167: 
                   1168:        if (senderaddress)
                   1169:        {
                   1170:                rewrite(pvp, 1);
                   1171:                if (m->m_s_rwset > 0)
                   1172:                        rewrite(pvp, m->m_s_rwset);
                   1173:        }
                   1174:        else
                   1175:        {
                   1176:                rewrite(pvp, 2);
                   1177:                if (m->m_r_rwset > 0)
                   1178:                        rewrite(pvp, m->m_r_rwset);
                   1179:        }
                   1180: 
                   1181:        /*
                   1182:        **  Do any final sanitation the address may require.
                   1183:        **      This will normally be used to turn internal forms
                   1184:        **      (e.g., [email protected]) into external form.  This
                   1185:        **      may be used as a default to the above rules.
                   1186:        */
                   1187: 
                   1188:        rewrite(pvp, 4);
                   1189: 
                   1190:        /*
                   1191:        **  Now restore the comment information we had at the beginning.
                   1192:        */
                   1193: 
                   1194:        cataddr(pvp, lbuf, sizeof lbuf);
                   1195:        define('g', lbuf, CurEnv);
                   1196:        expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
                   1197:        define('g', oldg, CurEnv);
                   1198: 
                   1199: # ifdef DEBUG
                   1200:        if (tTd(12, 1))
                   1201:                printf("remotename => `%s'\n", buf);
                   1202: # endif DEBUG
                   1203:        return (buf);
                   1204: }

unix.superglobalmegacorp.com

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