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

unix.superglobalmegacorp.com

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