Annotation of 42BSD/usr.lib/sendmail/src/parseaddr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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