home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / RCS / parseaddr.c,v < prev    next >
Encoding:
Text File  |  1991-06-25  |  46.3 KB  |  2,397 lines

  1. head    5.13;
  2. branch    5.13.0;
  3. access;
  4. symbols
  5.     RELEASE:5.13.0.18
  6.     BETA:5.13.0.16
  7.     UICSO:5.13.0
  8.     VANILLA:5.13;
  9. locks; strict;
  10. comment    @ * @;
  11.  
  12.  
  13. 5.13
  14. date    90.06.20.08.36.07;    author paul;    state Exp;
  15. branches
  16.     5.13.0.1;
  17. next    ;
  18.  
  19. 5.13.0.1
  20. date    90.06.20.09.43.24;    author paul;    state Exp;
  21. branches;
  22. next    5.13.0.2;
  23.  
  24. 5.13.0.2
  25. date    90.07.06.19.12.11;    author paul;    state Exp;
  26. branches;
  27. next    5.13.0.3;
  28.  
  29. 5.13.0.3
  30. date    90.09.17.09.33.01;    author paul;    state Exp;
  31. branches;
  32. next    5.13.0.4;
  33.  
  34. 5.13.0.4
  35. date    90.10.13.18.46.49;    author paul;    state Exp;
  36. branches;
  37. next    5.13.0.5;
  38.  
  39. 5.13.0.5
  40. date    90.11.02.15.03.33;    author paul;    state Exp;
  41. branches;
  42. next    5.13.0.6;
  43.  
  44. 5.13.0.6
  45. date    90.11.11.10.36.58;    author paul;    state Exp;
  46. branches;
  47. next    5.13.0.7;
  48.  
  49. 5.13.0.7
  50. date    90.11.24.03.05.28;    author paul;    state Exp;
  51. branches;
  52. next    5.13.0.8;
  53.  
  54. 5.13.0.8
  55. date    90.11.26.20.36.53;    author paul;    state Exp;
  56. branches;
  57. next    5.13.0.9;
  58.  
  59. 5.13.0.9
  60. date    90.11.28.16.30.48;    author paul;    state Exp;
  61. branches;
  62. next    5.13.0.10;
  63.  
  64. 5.13.0.10
  65. date    91.02.17.02.35.50;    author paul;    state Exp;
  66. branches;
  67. next    5.13.0.11;
  68.  
  69. 5.13.0.11
  70. date    91.02.17.04.42.34;    author paul;    state Exp;
  71. branches;
  72. next    5.13.0.12;
  73.  
  74. 5.13.0.12
  75. date    91.03.06.15.16.42;    author paul;    state Exp;
  76. branches;
  77. next    5.13.0.13;
  78.  
  79. 5.13.0.13
  80. date    91.04.05.14.55.15;    author paul;    state Exp;
  81. branches;
  82. next    5.13.0.14;
  83.  
  84. 5.13.0.14
  85. date    91.04.11.20.31.35;    author paul;    state Exp;
  86. branches;
  87. next    5.13.0.15;
  88.  
  89. 5.13.0.15
  90. date    91.04.25.22.19.43;    author paul;    state Exp;
  91. branches;
  92. next    5.13.0.16;
  93.  
  94. 5.13.0.16
  95. date    91.05.18.17.31.23;    author paul;    state Exp;
  96. branches;
  97. next    5.13.0.17;
  98.  
  99. 5.13.0.17
  100. date    91.06.24.14.24.26;    author paul;    state Exp;
  101. branches;
  102. next    5.13.0.18;
  103.  
  104. 5.13.0.18
  105. date    91.06.25.04.47.05;    author paul;    state Exp;
  106. branches;
  107. next    ;
  108.  
  109.  
  110. desc
  111. @@
  112.  
  113.  
  114. 5.13
  115. log
  116. @5.64 Berkeley release
  117. @
  118. text
  119. @/*
  120.  * Copyright (c) 1983 Eric P. Allman
  121.  * Copyright (c) 1988 Regents of the University of California.
  122.  * All rights reserved.
  123.  *
  124.  * Redistribution and use in source and binary forms are permitted provided
  125.  * that: (1) source distributions retain this entire copyright notice and
  126.  * comment, and (2) distributions including binaries display the following
  127.  * acknowledgement:  ``This product includes software developed by the
  128.  * University of California, Berkeley and its contributors'' in the
  129.  * documentation or other materials provided with the distribution and in
  130.  * all advertising materials mentioning features or use of this software.
  131.  * Neither the name of the University nor the names of its contributors may
  132.  * be used to endorse or promote products derived from this software without
  133.  * specific prior written permission.
  134.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  135.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  136.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  137.  */
  138.  
  139. #ifndef lint
  140. static char sccsid[] = "@@(#)parseaddr.c    5.13 (Berkeley) 6/1/90";
  141. #endif /* not lint */
  142.  
  143. # include "sendmail.h"
  144.  
  145. /*
  146. **  PARSEADDR -- Parse an address
  147. **
  148. **    Parses an address and breaks it up into three parts: a
  149. **    net to transmit the message on, the host to transmit it
  150. **    to, and a user on that host.  These are loaded into an
  151. **    ADDRESS header with the values squirreled away if necessary.
  152. **    The "user" part may not be a real user; the process may
  153. **    just reoccur on that machine.  For example, on a machine
  154. **    with an arpanet connection, the address
  155. **        csvax.bill@@berkeley
  156. **    will break up to a "user" of 'csvax.bill' and a host
  157. **    of 'berkeley' -- to be transmitted over the arpanet.
  158. **
  159. **    Parameters:
  160. **        addr -- the address to parse.
  161. **        a -- a pointer to the address descriptor buffer.
  162. **            If NULL, a header will be created.
  163. **        copyf -- determines what shall be copied:
  164. **            -1 -- don't copy anything.  The printname
  165. **                (q_paddr) is just addr, and the
  166. **                user & host are allocated internally
  167. **                to parse.
  168. **            0 -- copy out the parsed user & host, but
  169. **                don't copy the printname.
  170. **            +1 -- copy everything.
  171. **        delim -- the character to terminate the address, passed
  172. **            to prescan.
  173. **
  174. **    Returns:
  175. **        A pointer to the address descriptor header (`a' if
  176. **            `a' is non-NULL).
  177. **        NULL on error.
  178. **
  179. **    Side Effects:
  180. **        none
  181. */
  182.  
  183. /* following delimiters are inherent to the internal algorithms */
  184. # define DELIMCHARS    "\001()<>,;\\\"\r\n"    /* word delimiters */
  185.  
  186. ADDRESS *
  187. parseaddr(addr, a, copyf, delim)
  188.     char *addr;
  189.     register ADDRESS *a;
  190.     int copyf;
  191.     char delim;
  192. {
  193.     register char **pvp;
  194.     register struct mailer *m;
  195.     char pvpbuf[PSBUFSIZE];
  196.     extern char **prescan();
  197.     extern ADDRESS *buildaddr();
  198.  
  199.     /*
  200.     **  Initialize and prescan address.
  201.     */
  202.  
  203.     CurEnv->e_to = addr;
  204.     if (tTd(20, 1))
  205.         printf("\n--parseaddr(%s)\n", addr);
  206.  
  207.     pvp = prescan(addr, delim, pvpbuf);
  208.     if (pvp == NULL)
  209.         return (NULL);
  210.  
  211.     /*
  212.     **  Apply rewriting rules.
  213.     **    Ruleset 0 does basic parsing.  It must resolve.
  214.     */
  215.  
  216.     rewrite(pvp, 3);
  217.     rewrite(pvp, 0);
  218.  
  219.     /*
  220.     **  See if we resolved to a real mailer.
  221.     */
  222.  
  223.     if (pvp[0][0] != CANONNET)
  224.     {
  225.         setstat(EX_USAGE);
  226.         usrerr("cannot resolve name");
  227.         return (NULL);
  228.     }
  229.  
  230.     /*
  231.     **  Build canonical address from pvp.
  232.     */
  233.  
  234.     a = buildaddr(pvp, a);
  235.     if (a == NULL)
  236.         return (NULL);
  237.     m = a->q_mailer;
  238.  
  239.     /*
  240.     **  Make local copies of the host & user and then
  241.     **  transport them out.
  242.     */
  243.  
  244.     if (copyf > 0)
  245.     {
  246.         extern char *DelimChar;
  247.         char savec = *DelimChar;
  248.  
  249.         *DelimChar = '\0';
  250.         a->q_paddr = newstr(addr);
  251.         *DelimChar = savec;
  252.     }
  253.     else
  254.         a->q_paddr = addr;
  255.  
  256.     if (a->q_user == NULL)
  257.         a->q_user = "";
  258.     if (a->q_host == NULL)
  259.         a->q_host = "";
  260.  
  261.     if (copyf >= 0)
  262.     {
  263.         a->q_host = newstr(a->q_host);
  264.         if (a->q_user != a->q_paddr)
  265.             a->q_user = newstr(a->q_user);
  266.     }
  267.  
  268.     /*
  269.     **  Convert host name to lower case if requested.
  270.     **    User name will be done later.
  271.     */
  272.  
  273.     if (!bitnset(M_HST_UPPER, m->m_flags))
  274.         makelower(a->q_host);
  275.  
  276.     /*
  277.     **  Compute return value.
  278.     */
  279.  
  280.     if (tTd(20, 1))
  281.     {
  282.         printf("parseaddr-->");
  283.         printaddr(a, FALSE);
  284.     }
  285.  
  286.     return (a);
  287. }
  288. /*
  289. **  LOWERADDR -- map UPPER->lower case on addresses as requested.
  290. **
  291. **    Parameters:
  292. **        a -- address to be mapped.
  293. **
  294. **    Returns:
  295. **        none.
  296. **
  297. **    Side Effects:
  298. **        none.
  299. */
  300.  
  301. loweraddr(a)
  302.     register ADDRESS *a;
  303. {
  304.     register MAILER *m = a->q_mailer;
  305.  
  306.     if (!bitnset(M_USR_UPPER, m->m_flags))
  307.         makelower(a->q_user);
  308. }
  309. /*
  310. **  PRESCAN -- Prescan name and make it canonical
  311. **
  312. **    Scans a name and turns it into a set of tokens.  This process
  313. **    deletes blanks and comments (in parentheses).
  314. **
  315. **    This routine knows about quoted strings and angle brackets.
  316. **
  317. **    There are certain subtleties to this routine.  The one that
  318. **    comes to mind now is that backslashes on the ends of names
  319. **    are silently stripped off; this is intentional.  The problem
  320. **    is that some versions of sndmsg (like at LBL) set the kill
  321. **    character to something other than @@ when reading addresses;
  322. **    so people type "csvax.eric\@@berkeley" -- which screws up the
  323. **    berknet mailer.
  324. **
  325. **    Parameters:
  326. **        addr -- the name to chomp.
  327. **        delim -- the delimiter for the address, normally
  328. **            '\0' or ','; \0 is accepted in any case.
  329. **            If '\t' then we are reading the .cf file.
  330. **        pvpbuf -- place to put the saved text -- note that
  331. **            the pointers are static.
  332. **
  333. **    Returns:
  334. **        A pointer to a vector of tokens.
  335. **        NULL on error.
  336. **
  337. **    Side Effects:
  338. **        sets DelimChar to point to the character matching 'delim'.
  339. */
  340.  
  341. /* states and character types */
  342. # define OPR        0    /* operator */
  343. # define ATM        1    /* atom */
  344. # define QST        2    /* in quoted string */
  345. # define SPC        3    /* chewing up spaces */
  346. # define ONE        4    /* pick up one character */
  347.  
  348. # define NSTATES    5    /* number of states */
  349. # define TYPE        017    /* mask to select state type */
  350.  
  351. /* meta bits for table */
  352. # define M        020    /* meta character; don't pass through */
  353. # define B        040    /* cause a break */
  354. # define MB        M|B    /* meta-break */
  355.  
  356. static short StateTab[NSTATES][NSTATES] =
  357. {
  358.    /*    oldst    chtype>    OPR    ATM    QST    SPC    ONE    */
  359.     /*OPR*/        OPR|B,    ATM|B,    QST|B,    SPC|MB,    ONE|B,
  360.     /*ATM*/        OPR|B,    ATM,    QST|B,    SPC|MB,    ONE|B,
  361.     /*QST*/        QST,    QST,    OPR,    QST,    QST,
  362.     /*SPC*/        OPR,    ATM,    QST,    SPC|M,    ONE,
  363.     /*ONE*/        OPR,    OPR,    OPR,    OPR,    OPR,
  364. };
  365.  
  366. # define NOCHAR        -1    /* signal nothing in lookahead token */
  367.  
  368. char    *DelimChar;        /* set to point to the delimiter */
  369.  
  370. char **
  371. prescan(addr, delim, pvpbuf)
  372.     char *addr;
  373.     char delim;
  374.     char pvpbuf[];
  375. {
  376.     register char *p;
  377.     register char *q;
  378.     register int c;
  379.     char **avp;
  380.     bool bslashmode;
  381.     int cmntcnt;
  382.     int anglecnt;
  383.     char *tok;
  384.     int state;
  385.     int newstate;
  386.     static char *av[MAXATOM+1];
  387.     extern int errno;
  388.  
  389.     /* make sure error messages don't have garbage on them */
  390.     errno = 0;
  391.  
  392.     q = pvpbuf;
  393.     bslashmode = FALSE;
  394.     cmntcnt = 0;
  395.     anglecnt = 0;
  396.     avp = av;
  397.     state = OPR;
  398.     c = NOCHAR;
  399.     p = addr;
  400.     if (tTd(22, 45))
  401.     {
  402.         printf("prescan: ");
  403.         xputs(p);
  404.         (void) putchar('\n');
  405.     }
  406.  
  407.     do
  408.     {
  409.         /* read a token */
  410.         tok = q;
  411.         for (;;)
  412.         {
  413.             /* store away any old lookahead character */
  414.             if (c != NOCHAR)
  415.             {
  416.                 /* see if there is room */
  417.                 if (q >= &pvpbuf[PSBUFSIZE - 5])
  418.                 {
  419.                     usrerr("Address too long");
  420.                     DelimChar = p;
  421.                     return (NULL);
  422.                 }
  423.  
  424.                 /* squirrel it away */
  425.                 *q++ = c;
  426.             }
  427.  
  428.             /* read a new input character */
  429.             c = *p++;
  430.             if (c == '\0')
  431.                 break;
  432.             c &= ~0200;
  433.  
  434.             if (tTd(22, 101))
  435.                 printf("c=%c, s=%d; ", c, state);
  436.  
  437.             /* chew up special characters */
  438.             *q = '\0';
  439.             if (bslashmode)
  440.             {
  441.                 /* kludge \! for naive users */
  442.                 if (c != '!')
  443.                     c |= 0200;
  444.                 bslashmode = FALSE;
  445.             }
  446.             else if (c == '\\')
  447.             {
  448.                 bslashmode = TRUE;
  449.                 c = NOCHAR;
  450.             }
  451.             else if (state == QST)
  452.             {
  453.                 /* do nothing, just avoid next clauses */
  454.             }
  455.             else if (c == '(')
  456.             {
  457.                 cmntcnt++;
  458.                 c = NOCHAR;
  459.             }
  460.             else if (c == ')')
  461.             {
  462.                 if (cmntcnt <= 0)
  463.                 {
  464.                     usrerr("Unbalanced ')'");
  465.                     DelimChar = p;
  466.                     return (NULL);
  467.                 }
  468.                 else
  469.                     cmntcnt--;
  470.             }
  471.             else if (cmntcnt > 0)
  472.                 c = NOCHAR;
  473.             else if (c == '<')
  474.                 anglecnt++;
  475.             else if (c == '>')
  476.             {
  477.                 if (anglecnt <= 0)
  478.                 {
  479.                     usrerr("Unbalanced '>'");
  480.                     DelimChar = p;
  481.                     return (NULL);
  482.                 }
  483.                 anglecnt--;
  484.             }
  485.             else if (delim == ' ' && isspace(c))
  486.                 c = ' ';
  487.  
  488.             if (c == NOCHAR)
  489.                 continue;
  490.  
  491.             /* see if this is end of input */
  492.             if (c == delim && anglecnt <= 0 && state != QST)
  493.                 break;
  494.  
  495.             newstate = StateTab[state][toktype(c)];
  496.             if (tTd(22, 101))
  497.                 printf("ns=%02o\n", newstate);
  498.             state = newstate & TYPE;
  499.             if (bitset(M, newstate))
  500.                 c = NOCHAR;
  501.             if (bitset(B, newstate))
  502.                 break;
  503.         }
  504.  
  505.         /* new token */
  506.         if (tok != q)
  507.         {
  508.             *q++ = '\0';
  509.             if (tTd(22, 36))
  510.             {
  511.                 printf("tok=");
  512.                 xputs(tok);
  513.                 (void) putchar('\n');
  514.             }
  515.             if (avp >= &av[MAXATOM])
  516.             {
  517.                 syserr("prescan: too many tokens");
  518.                 DelimChar = p;
  519.                 return (NULL);
  520.             }
  521.             *avp++ = tok;
  522.         }
  523.     } while (c != '\0' && (c != delim || anglecnt > 0));
  524.     *avp = NULL;
  525.     DelimChar = --p;
  526.     if (cmntcnt > 0)
  527.         usrerr("Unbalanced '('");
  528.     else if (anglecnt > 0)
  529.         usrerr("Unbalanced '<'");
  530.     else if (state == QST)
  531.         usrerr("Unbalanced '\"'");
  532.     else if (av[0] != NULL)
  533.         return (av);
  534.     return (NULL);
  535. }
  536. /*
  537. **  TOKTYPE -- return token type
  538. **
  539. **    Parameters:
  540. **        c -- the character in question.
  541. **
  542. **    Returns:
  543. **        Its type.
  544. **
  545. **    Side Effects:
  546. **        none.
  547. */
  548.  
  549. toktype(c)
  550.     register char c;
  551. {
  552.     static char buf[50];
  553.     static bool firstime = TRUE;
  554.  
  555.     if (firstime)
  556.     {
  557.         firstime = FALSE;
  558.         expand("\001o", buf, &buf[sizeof buf - 1], CurEnv);
  559.         (void) strcat(buf, DELIMCHARS);
  560.     }
  561.     if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
  562.         return (ONE);
  563.     if (c == '"')
  564.         return (QST);
  565.     if (!isascii(c))
  566.         return (ATM);
  567.     if (isspace(c) || c == ')')
  568.         return (SPC);
  569.     if (iscntrl(c) || index(buf, c) != NULL)
  570.         return (OPR);
  571.     return (ATM);
  572. }
  573. /*
  574. **  REWRITE -- apply rewrite rules to token vector.
  575. **
  576. **    This routine is an ordered production system.  Each rewrite
  577. **    rule has a LHS (called the pattern) and a RHS (called the
  578. **    rewrite); 'rwr' points the the current rewrite rule.
  579. **
  580. **    For each rewrite rule, 'avp' points the address vector we
  581. **    are trying to match against, and 'pvp' points to the pattern.
  582. **    If pvp points to a special match value (MATCHZANY, MATCHANY,
  583. **    MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp
  584. **    matched is saved away in the match vector (pointed to by 'mvp').
  585. **
  586. **    When a match between avp & pvp does not match, we try to
  587. **    back out.  If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS
  588. **    we must also back out the match in mvp.  If we reach a
  589. **    MATCHANY or MATCHZANY we just extend the match and start
  590. **    over again.
  591. **
  592. **    When we finally match, we rewrite the address vector
  593. **    and try over again.
  594. **
  595. **    Parameters:
  596. **        pvp -- pointer to token vector.
  597. **
  598. **    Returns:
  599. **        none.
  600. **
  601. **    Side Effects:
  602. **        pvp is modified.
  603. */
  604.  
  605. struct match
  606. {
  607.     char    **first;    /* first token matched */
  608.     char    **last;        /* last token matched */
  609. };
  610.  
  611. # define MAXMATCH    9    /* max params per rewrite */
  612.  
  613.  
  614. rewrite(pvp, ruleset)
  615.     char **pvp;
  616.     int ruleset;
  617. {
  618.     register char *ap;        /* address pointer */
  619.     register char *rp;        /* rewrite pointer */
  620.     register char **avp;        /* address vector pointer */
  621.     register char **rvp;        /* rewrite vector pointer */
  622.     register struct match *mlp;    /* cur ptr into mlist */
  623.     register struct rewrite *rwr;    /* pointer to current rewrite rule */
  624.     struct match mlist[MAXMATCH];    /* stores match on LHS */
  625.     char *npvp[MAXATOM+1];        /* temporary space for rebuild */
  626.  
  627.     if (OpMode == MD_TEST || tTd(21, 2))
  628.     {
  629.         printf("rewrite: ruleset %2d   input:", ruleset);
  630.         printav(pvp);
  631.     }
  632.     if (pvp == NULL)
  633.         return;
  634.  
  635.     /*
  636.     **  Run through the list of rewrite rules, applying
  637.     **    any that match.
  638.     */
  639.  
  640.     for (rwr = RewriteRules[ruleset]; rwr != NULL; )
  641.     {
  642.         if (tTd(21, 12))
  643.         {
  644.             printf("-----trying rule:");
  645.             printav(rwr->r_lhs);
  646.         }
  647.  
  648.         /* try to match on this rule */
  649.         mlp = mlist;
  650.         rvp = rwr->r_lhs;
  651.         avp = pvp;
  652.         while ((ap = *avp) != NULL || *rvp != NULL)
  653.         {
  654.             rp = *rvp;
  655.             if (tTd(21, 35))
  656.             {
  657.                 printf("ap=");
  658.                 xputs(ap);
  659.                 printf(", rp=");
  660.                 xputs(rp);
  661.                 printf("\n");
  662.             }
  663.             if (rp == NULL)
  664.             {
  665.                 /* end-of-pattern before end-of-address */
  666.                 goto backup;
  667.             }
  668.             if (ap == NULL && *rp != MATCHZANY)
  669.             {
  670.                 /* end-of-input */
  671.                 break;
  672.             }
  673.  
  674.             switch (*rp)
  675.             {
  676.                 register STAB *s;
  677.  
  678.               case MATCHCLASS:
  679.               case MATCHNCLASS:
  680.                 /* match any token in (not in) a class */
  681.                 s = stab(ap, ST_CLASS, ST_FIND);
  682.                 if (s == NULL || !bitnset(rp[1], s->s_class))
  683.                 {
  684.                     if (*rp == MATCHCLASS)
  685.                         goto backup;
  686.                 }
  687.                 else if (*rp == MATCHNCLASS)
  688.                     goto backup;
  689.  
  690.                 /* explicit fall-through */
  691.  
  692.               case MATCHONE:
  693.               case MATCHANY:
  694.                 /* match exactly one token */
  695.                 mlp->first = avp;
  696.                 mlp->last = avp++;
  697.                 mlp++;
  698.                 break;
  699.  
  700.               case MATCHZANY:
  701.                 /* match zero or more tokens */
  702.                 mlp->first = avp;
  703.                 mlp->last = avp - 1;
  704.                 mlp++;
  705.                 break;
  706.  
  707.               default:
  708.                 /* must have exact match */
  709.                 if (strcasecmp(rp, ap))
  710.                     goto backup;
  711.                 avp++;
  712.                 break;
  713.             }
  714.  
  715.             /* successful match on this token */
  716.             rvp++;
  717.             continue;
  718.  
  719.           backup:
  720.             /* match failed -- back up */
  721.             while (--rvp >= rwr->r_lhs)
  722.             {
  723.                 rp = *rvp;
  724.                 if (*rp == MATCHANY || *rp == MATCHZANY)
  725.                 {
  726.                     /* extend binding and continue */
  727.                     avp = ++mlp[-1].last;
  728.                     avp++;
  729.                     rvp++;
  730.                     break;
  731.                 }
  732.                 avp--;
  733.                 if (*rp == MATCHONE || *rp == MATCHCLASS ||
  734.                     *rp == MATCHNCLASS)
  735.                 {
  736.                     /* back out binding */
  737.                     mlp--;
  738.                 }
  739.             }
  740.  
  741.             if (rvp < rwr->r_lhs)
  742.             {
  743.                 /* total failure to match */
  744.                 break;
  745.             }
  746.         }
  747.  
  748.         /*
  749.         **  See if we successfully matched
  750.         */
  751.  
  752.         if (rvp < rwr->r_lhs || *rvp != NULL)
  753.         {
  754.             if (tTd(21, 10))
  755.                 printf("----- rule fails\n");
  756.             rwr = rwr->r_next;
  757.             continue;
  758.         }
  759.  
  760.         rvp = rwr->r_rhs;
  761.         if (tTd(21, 12))
  762.         {
  763.             printf("-----rule matches:");
  764.             printav(rvp);
  765.         }
  766.  
  767.         rp = *rvp;
  768.         if (*rp == CANONUSER)
  769.         {
  770.             rvp++;
  771.             rwr = rwr->r_next;
  772.         }
  773.         else if (*rp == CANONHOST)
  774.         {
  775.             rvp++;
  776.             rwr = NULL;
  777.         }
  778.         else if (*rp == CANONNET)
  779.             rwr = NULL;
  780.  
  781.         /* substitute */
  782.         for (avp = npvp; *rvp != NULL; rvp++)
  783.         {
  784.             register struct match *m;
  785.             register char **pp;
  786.  
  787.             rp = *rvp;
  788.             if (*rp == MATCHREPL)
  789.             {
  790.                 /* substitute from LHS */
  791.                 m = &mlist[rp[1] - '1'];
  792.                 if (m >= mlp)
  793.                 {
  794.                     syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);
  795.                     return;
  796.                 }
  797.                 if (tTd(21, 15))
  798.                 {
  799.                     printf("$%c:", rp[1]);
  800.                     pp = m->first;
  801.                     while (pp <= m->last)
  802.                     {
  803.                         printf(" %x=\"", *pp);
  804.                         (void) fflush(stdout);
  805.                         printf("%s\"", *pp++);
  806.                     }
  807.                     printf("\n");
  808.                 }
  809.                 pp = m->first;
  810.                 while (pp <= m->last)
  811.                 {
  812.                     if (avp >= &npvp[MAXATOM])
  813.                     {
  814.                         syserr("rewrite: expansion too long");
  815.                         return;
  816.                     }
  817.                     *avp++ = *pp++;
  818.                 }
  819.             }
  820.             else
  821.             {
  822.                 /* vanilla replacement */
  823.                 if (avp >= &npvp[MAXATOM])
  824.                 {
  825.     toolong:
  826.                     syserr("rewrite: expansion too long");
  827.                     return;
  828.                 }
  829.                 *avp++ = rp;
  830.             }
  831.         }
  832.         *avp++ = NULL;
  833.  
  834.         /*
  835.         **  Check for any hostname lookups.
  836.         */
  837.  
  838.         for (rvp = npvp; *rvp != NULL; rvp++)
  839.         {
  840.             char **hbrvp;
  841.             char **xpvp;
  842.             int trsize;
  843.             char *olddelimchar;
  844.             char buf[MAXNAME + 1];
  845.             char *pvpb1[MAXATOM + 1];
  846.             char pvpbuf[PSBUFSIZE];
  847.             extern char *DelimChar;
  848.  
  849.             if (**rvp != HOSTBEGIN)
  850.                 continue;
  851.  
  852.             /*
  853.             **  Got a hostname lookup.
  854.             **
  855.             **    This could be optimized fairly easily.
  856.             */
  857.  
  858.             hbrvp = rvp;
  859.  
  860.             /* extract the match part */
  861.             while (*++rvp != NULL && **rvp != HOSTEND)
  862.                 continue;
  863.             if (*rvp != NULL)
  864.                 *rvp++ = NULL;
  865.  
  866.             /* save the remainder of the input string */
  867.             trsize = (int) (avp - rvp + 1) * sizeof *rvp;
  868.             bcopy((char *) rvp, (char *) pvpb1, trsize);
  869.  
  870.             /* look it up */
  871.             cataddr(++hbrvp, buf, sizeof buf);
  872.             maphostname(buf, sizeof buf);
  873.  
  874.             /* scan the new host name */
  875.             olddelimchar = DelimChar;
  876.             xpvp = prescan(buf, '\0', pvpbuf);
  877.             DelimChar = olddelimchar;
  878.             if (xpvp == NULL)
  879.             {
  880.                 syserr("rewrite: cannot prescan canonical hostname: %s", buf);
  881.                 return;
  882.             }
  883.  
  884.             /* append it to the token list */
  885.             for (avp = --hbrvp; *xpvp != NULL; xpvp++)
  886.             {
  887.                 *avp++ = newstr(*xpvp);
  888.                 if (avp >= &npvp[MAXATOM])
  889.                     goto toolong;
  890.             }
  891.  
  892.             /* restore the old trailing information */
  893.             for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
  894.                 if (avp >= &npvp[MAXATOM])
  895.                     goto toolong;
  896.  
  897.             break;
  898.         }
  899.  
  900.         /*
  901.         **  Check for subroutine calls.
  902.         */
  903.  
  904.         if (*npvp != NULL && **npvp == CALLSUBR)
  905.         {
  906.             bcopy((char *) &npvp[2], (char *) pvp,
  907.                 (int) (avp - npvp - 2) * sizeof *avp);
  908.             if (tTd(21, 3))
  909.                 printf("-----callsubr %s\n", npvp[1]);
  910.             rewrite(pvp, atoi(npvp[1]));
  911.         }
  912.         else
  913.         {
  914.             bcopy((char *) npvp, (char *) pvp,
  915.                 (int) (avp - npvp) * sizeof *avp);
  916.         }
  917.         if (tTd(21, 4))
  918.         {
  919.             printf("rewritten as:");
  920.             printav(pvp);
  921.         }
  922.     }
  923.  
  924.     if (OpMode == MD_TEST || tTd(21, 2))
  925.     {
  926.         printf("rewrite: ruleset %2d returns:", ruleset);
  927.         printav(pvp);
  928.     }
  929. }
  930. /*
  931. **  BUILDADDR -- build address from token vector.
  932. **
  933. **    Parameters:
  934. **        tv -- token vector.
  935. **        a -- pointer to address descriptor to fill.
  936. **            If NULL, one will be allocated.
  937. **
  938. **    Returns:
  939. **        NULL if there was an error.
  940. **        'a' otherwise.
  941. **
  942. **    Side Effects:
  943. **        fills in 'a'
  944. */
  945.  
  946. ADDRESS *
  947. buildaddr(tv, a)
  948.     register char **tv;
  949.     register ADDRESS *a;
  950. {
  951.     static char buf[MAXNAME];
  952.     struct mailer **mp;
  953.     register struct mailer *m;
  954.  
  955.     if (a == NULL)
  956.         a = (ADDRESS *) xalloc(sizeof *a);
  957.     bzero((char *) a, sizeof *a);
  958.  
  959.     /* figure out what net/mailer to use */
  960.     if (**tv != CANONNET)
  961.     {
  962.         syserr("buildaddr: no net");
  963.         return (NULL);
  964.     }
  965.     tv++;
  966.     if (!strcasecmp(*tv, "error"))
  967.     {
  968.         if (**++tv == CANONHOST)
  969.         {
  970.             setstat(atoi(*++tv));
  971.             tv++;
  972.         }
  973.         if (**tv != CANONUSER)
  974.             syserr("buildaddr: error: no user");
  975.         buf[0] = '\0';
  976.         while (*++tv != NULL)
  977.         {
  978.             if (buf[0] != '\0')
  979.                 (void) strcat(buf, " ");
  980.             (void) strcat(buf, *tv);
  981.         }
  982.         usrerr(buf);
  983.         return (NULL);
  984.     }
  985.     for (mp = Mailer; (m = *mp++) != NULL; )
  986.     {
  987.         if (!strcasecmp(m->m_name, *tv))
  988.             break;
  989.     }
  990.     if (m == NULL)
  991.     {
  992.         syserr("buildaddr: unknown mailer %s", *tv);
  993.         return (NULL);
  994.     }
  995.     a->q_mailer = m;
  996.  
  997.     /* figure out what host (if any) */
  998.     tv++;
  999.     if (!bitnset(M_LOCAL, m->m_flags))
  1000.     {
  1001.         if (**tv++ != CANONHOST)
  1002.         {
  1003.             syserr("buildaddr: no host");
  1004.             return (NULL);
  1005.         }
  1006.         buf[0] = '\0';
  1007.         while (*tv != NULL && **tv != CANONUSER)
  1008.             (void) strcat(buf, *tv++);
  1009.         a->q_host = newstr(buf);
  1010.     }
  1011.     else
  1012.         a->q_host = NULL;
  1013.  
  1014.     /* figure out the user */
  1015.     if (*tv == NULL || **tv != CANONUSER)
  1016.     {
  1017.         syserr("buildaddr: no user");
  1018.         return (NULL);
  1019.     }
  1020.  
  1021.     /* rewrite according recipient mailer rewriting rules */
  1022.     rewrite(++tv, 2);
  1023.     if (m->m_r_rwset > 0)
  1024.         rewrite(tv, m->m_r_rwset);
  1025.     rewrite(tv, 4);
  1026.  
  1027.     /* save the result for the command line/RCPT argument */
  1028.     cataddr(tv, buf, sizeof buf);
  1029.     a->q_user = buf;
  1030.  
  1031.     return (a);
  1032. }
  1033. /*
  1034. **  CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
  1035. **
  1036. **    Parameters:
  1037. **        pvp -- parameter vector to rebuild.
  1038. **        buf -- buffer to build the string into.
  1039. **        sz -- size of buf.
  1040. **
  1041. **    Returns:
  1042. **        none.
  1043. **
  1044. **    Side Effects:
  1045. **        Destroys buf.
  1046. */
  1047.  
  1048. cataddr(pvp, buf, sz)
  1049.     char **pvp;
  1050.     char *buf;
  1051.     register int sz;
  1052. {
  1053.     bool oatomtok = FALSE;
  1054.     bool natomtok = FALSE;
  1055.     register int i;
  1056.     register char *p;
  1057.  
  1058.     if (pvp == NULL)
  1059.     {
  1060.         (void) strcpy(buf, "");
  1061.         return;
  1062.     }
  1063.     p = buf;
  1064.     sz -= 2;
  1065.     while (*pvp != NULL && (i = strlen(*pvp)) < sz)
  1066.     {
  1067.         natomtok = (toktype(**pvp) == ATM);
  1068.         if (oatomtok && natomtok)
  1069.             *p++ = SpaceSub;
  1070.         (void) strcpy(p, *pvp);
  1071.         oatomtok = natomtok;
  1072.         p += i;
  1073.         sz -= i + 1;
  1074.         pvp++;
  1075.     }
  1076.     *p = '\0';
  1077. }
  1078. /*
  1079. **  SAMEADDR -- Determine if two addresses are the same
  1080. **
  1081. **    This is not just a straight comparison -- if the mailer doesn't
  1082. **    care about the host we just ignore it, etc.
  1083. **
  1084. **    Parameters:
  1085. **        a, b -- pointers to the internal forms to compare.
  1086. **
  1087. **    Returns:
  1088. **        TRUE -- they represent the same mailbox.
  1089. **        FALSE -- they don't.
  1090. **
  1091. **    Side Effects:
  1092. **        none.
  1093. */
  1094.  
  1095. bool
  1096. sameaddr(a, b)
  1097.     register ADDRESS *a;
  1098.     register ADDRESS *b;
  1099. {
  1100.     /* if they don't have the same mailer, forget it */
  1101.     if (a->q_mailer != b->q_mailer)
  1102.         return (FALSE);
  1103.  
  1104.     /* if the user isn't the same, we can drop out */
  1105.     if (strcmp(a->q_user, b->q_user) != 0)
  1106.         return (FALSE);
  1107.  
  1108.     /* if the mailer ignores hosts, we have succeeded! */
  1109.     if (bitnset(M_LOCAL, a->q_mailer->m_flags))
  1110.         return (TRUE);
  1111.  
  1112.     /* otherwise compare hosts (but be careful for NULL ptrs) */
  1113.     if (a->q_host == NULL || b->q_host == NULL)
  1114.         return (FALSE);
  1115.     if (strcmp(a->q_host, b->q_host) != 0)
  1116.         return (FALSE);
  1117.  
  1118.     return (TRUE);
  1119. }
  1120. /*
  1121. **  PRINTADDR -- print address (for debugging)
  1122. **
  1123. **    Parameters:
  1124. **        a -- the address to print
  1125. **        follow -- follow the q_next chain.
  1126. **
  1127. **    Returns:
  1128. **        none.
  1129. **
  1130. **    Side Effects:
  1131. **        none.
  1132. */
  1133.  
  1134. printaddr(a, follow)
  1135.     register ADDRESS *a;
  1136.     bool follow;
  1137. {
  1138.     bool first = TRUE;
  1139.  
  1140.     while (a != NULL)
  1141.     {
  1142.         first = FALSE;
  1143.         printf("%x=", a);
  1144.         (void) fflush(stdout);
  1145.         printf("%s: mailer %d (%s), host `%s', user `%s', ruser `%s'\n",
  1146.                a->q_paddr, a->q_mailer->m_mno, a->q_mailer->m_name,
  1147.                a->q_host, a->q_user, a->q_ruser? a->q_ruser: "<null>");
  1148.         printf("\tnext=%x, flags=%o, alias %x\n", a->q_next, a->q_flags,
  1149.                a->q_alias);
  1150.         printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home,
  1151.                a->q_fullname);
  1152.  
  1153.         if (!follow)
  1154.             return;
  1155.         a = a->q_next;
  1156.     }
  1157.     if (first)
  1158.         printf("[NULL]\n");
  1159. }
  1160.  
  1161. /*
  1162. **  REMOTENAME -- return the name relative to the current mailer
  1163. **
  1164. **    Parameters:
  1165. **        name -- the name to translate.
  1166. **        m -- the mailer that we want to do rewriting relative
  1167. **            to.
  1168. **        senderaddress -- if set, uses the sender rewriting rules
  1169. **            rather than the recipient rewriting rules.
  1170. **        canonical -- if set, strip out any comment information,
  1171. **            etc.
  1172. **
  1173. **    Returns:
  1174. **        the text string representing this address relative to
  1175. **            the receiving mailer.
  1176. **
  1177. **    Side Effects:
  1178. **        none.
  1179. **
  1180. **    Warnings:
  1181. **        The text string returned is tucked away locally;
  1182. **            copy it if you intend to save it.
  1183. */
  1184.  
  1185. char *
  1186. remotename(name, m, senderaddress, canonical)
  1187.     char *name;
  1188.     struct mailer *m;
  1189.     bool senderaddress;
  1190.     bool canonical;
  1191. {
  1192.     register char **pvp;
  1193.     char *fancy;
  1194.     extern char *macvalue();
  1195.     char *oldg = macvalue('g', CurEnv);
  1196.     static char buf[MAXNAME];
  1197.     char lbuf[MAXNAME];
  1198.     char pvpbuf[PSBUFSIZE];
  1199.     extern char **prescan();
  1200.     extern char *crackaddr();
  1201.  
  1202.     if (tTd(12, 1))
  1203.         printf("remotename(%s)\n", name);
  1204.  
  1205.     /* don't do anything if we are tagging it as special */
  1206.     if ((senderaddress ? m->m_s_rwset : m->m_r_rwset) < 0)
  1207.         return (name);
  1208.  
  1209.     /*
  1210.     **  Do a heuristic crack of this name to extract any comment info.
  1211.     **    This will leave the name as a comment and a $g macro.
  1212.     */
  1213.  
  1214.     if (canonical)
  1215.         fancy = "\001g";
  1216.     else
  1217.         fancy = crackaddr(name);
  1218.  
  1219.     /*
  1220.     **  Turn the name into canonical form.
  1221.     **    Normally this will be RFC 822 style, i.e., "user@@domain".
  1222.     **    If this only resolves to "user", and the "C" flag is
  1223.     **    specified in the sending mailer, then the sender's
  1224.     **    domain will be appended.
  1225.     */
  1226.  
  1227.     pvp = prescan(name, '\0', pvpbuf);
  1228.     if (pvp == NULL)
  1229.         return (name);
  1230.     rewrite(pvp, 3);
  1231.     if (CurEnv->e_fromdomain != NULL)
  1232.     {
  1233.         /* append from domain to this address */
  1234.         register char **pxp = pvp;
  1235.  
  1236.         /* see if there is an "@@domain" in the current name */
  1237.         while (*pxp != NULL && strcmp(*pxp, "@@") != 0)
  1238.             pxp++;
  1239.         if (*pxp == NULL)
  1240.         {
  1241.             /* no.... append the "@@domain" from the sender */
  1242.             register char **qxq = CurEnv->e_fromdomain;
  1243.  
  1244.             while ((*pxp++ = *qxq++) != NULL)
  1245.                 continue;
  1246.             rewrite(pvp, 3);
  1247.         }
  1248.     }
  1249.  
  1250.     /*
  1251.     **  Do more specific rewriting.
  1252.     **    Rewrite using ruleset 1 or 2 depending on whether this is
  1253.     **        a sender address or not.
  1254.     **    Then run it through any receiving-mailer-specific rulesets.
  1255.     */
  1256.  
  1257.     if (senderaddress)
  1258.     {
  1259.         rewrite(pvp, 1);
  1260.         if (m->m_s_rwset > 0)
  1261.             rewrite(pvp, m->m_s_rwset);
  1262.     }
  1263.     else
  1264.     {
  1265.         rewrite(pvp, 2);
  1266.         if (m->m_r_rwset > 0)
  1267.             rewrite(pvp, m->m_r_rwset);
  1268.     }
  1269.  
  1270.     /*
  1271.     **  Do any final sanitation the address may require.
  1272.     **    This will normally be used to turn internal forms
  1273.     **    (e.g., user@@host.LOCAL) into external form.  This
  1274.     **    may be used as a default to the above rules.
  1275.     */
  1276.  
  1277.     rewrite(pvp, 4);
  1278.  
  1279.     /*
  1280.     **  Now restore the comment information we had at the beginning.
  1281.     */
  1282.  
  1283.     cataddr(pvp, lbuf, sizeof lbuf);
  1284.     define('g', lbuf, CurEnv);
  1285.     expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
  1286.     define('g', oldg, CurEnv);
  1287.  
  1288.     if (tTd(12, 1))
  1289.         printf("remotename => `%s'\n", buf);
  1290.     return (buf);
  1291. }
  1292. @
  1293.  
  1294.  
  1295. 5.13.0.1
  1296. log
  1297. @IDA patches
  1298. @
  1299. text
  1300. @a444 4
  1301. #ifdef MACVALUE
  1302.     if (c == MACVALUE)
  1303.         return (ONE);
  1304. #endif MACVALUE
  1305. a494 1
  1306. static int nrw;
  1307. a499 8
  1308.     nrw = 0;
  1309.     _rewrite(pvp, ruleset);
  1310. }
  1311.  
  1312. _rewrite(pvp, ruleset)
  1313.     char **pvp;
  1314.     int ruleset;
  1315. {
  1316. a507 2
  1317.     char tokbuf[MAXNAME+1];        /* for concatenated class tokens */
  1318.      int nloops, nmatches = 0;    /* for looping rule checks */
  1319. d512 1
  1320. a512 1
  1321.         printcav(pvp);
  1322. a516 10
  1323.     if (++nrw > 100) {
  1324.         char buf[MAXLINE];
  1325.  
  1326.         buf[0] = buf[MAXLINE-1] = 0;
  1327.         while (*pvp)
  1328.             strncat(buf, *pvp++, sizeof buf);
  1329.         syserr("address causes rewrite loop: <%s>", buf);
  1330.         return;
  1331.     }
  1332.  
  1333. d527 1
  1334. a527 1
  1335.             printcav(rwr->r_lhs);
  1336. a533 1
  1337.         nloops = 0;
  1338. a535 5
  1339.             if (nloops++ > 200) {
  1340.                 syserr("Looping on ruleset %d, rule %d",
  1341.                     ruleset, rwr-RewriteRules[ruleset]);
  1342.                 break;
  1343.             }
  1344. a558 1
  1345.                 char **oldavp;
  1346. d560 1
  1347. d562 1
  1348. a562 1
  1349.                 /* match any single token not in a class */
  1350. d564 3
  1351. a566 1
  1352.                 if (s != NULL && bitnset(rp[1], s->s_class))
  1353. d568 2
  1354. a569 16
  1355.  
  1356.                 /* match exactly one token */
  1357.                 mlp->first = avp;
  1358.                 mlp->last = avp++;
  1359.                 mlp++;
  1360.                 break;
  1361.  
  1362.               case MATCHCLASS:
  1363.                 /* match any token in a class */
  1364.                 /* slow, concat version by lel@@ida.liu.se */
  1365.                 /* handles multi-token class matches, though */
  1366.                 oldavp = avp;
  1367.                 *tokbuf = NULL;
  1368.                 do {
  1369.                     if (*avp == NULL) {
  1370.                         avp = oldavp;
  1371. a570 4
  1372.                     }
  1373.                     strcat(tokbuf, *avp++);
  1374.                     s = stab(tokbuf, ST_CLASS, ST_FIND);
  1375.                 } while (s == NULL || !bitnset(rp[1], s->s_class));
  1376. d572 1
  1377. a572 4
  1378.                 mlp->first = oldavp;
  1379.                 mlp->last = avp-1;
  1380.                 mlp++;
  1381.                 break;
  1382. a605 31
  1383.                 if (*rp == MATCHCLASS) {
  1384.                     register STAB *s;
  1385.                     char **oldavp;
  1386.  
  1387.                     /* attempt to extend binding */
  1388.                     /* slow, concat version by lel@@ida.liu.se */
  1389.  
  1390.                     oldavp = avp;
  1391.                     *tokbuf = NULL;
  1392.                     for (avp = mlp[-1].first;
  1393.                         avp <= mlp[-1].last; avp++)
  1394.                         strcat(tokbuf, *avp);
  1395.  
  1396.                     do {
  1397.                         if (*avp == NULL) {
  1398.                             /* back out binding */
  1399.                             avp = oldavp;
  1400.                             mlp--;
  1401.                             goto cantextend;
  1402.                         }
  1403.                         strcat(tokbuf, *avp++);
  1404.                         s = stab(tokbuf, ST_CLASS, ST_FIND);
  1405.                     } while (s == NULL ||
  1406.                         !bitnset(rp[1], s->s_class));
  1407.  
  1408.                     /* found an extension */
  1409.                     mlp[-1].last = avp-1;
  1410.                     rvp++;
  1411.                     break;
  1412.                 }
  1413. cantextend:
  1414. d615 2
  1415. a616 1
  1416.                 if (*rp == MATCHONE || *rp == MATCHNCLASS)
  1417. a638 1
  1418.             nmatches = 0;
  1419. a641 8
  1420.         if (nmatches++ > 200) {
  1421.             syserr("Loop in ruleset %d, rule %d (too many matches)",
  1422.                 ruleset, rwr-RewriteRules[ruleset]);
  1423.             rwr = rwr->r_next;
  1424.             nmatches = 0;
  1425.             continue;
  1426.         }
  1427.  
  1428. d646 1
  1429. a646 1
  1430.             printcav(rvp);
  1431. a653 1
  1432.             nmatches = 0;
  1433. d676 1
  1434. a676 2
  1435.                     syserr("rewrite: ruleset %d: replacement #%c out of bounds",
  1436.                         ruleset, rp[1]);
  1437. d711 1
  1438. a711 13
  1439. #ifdef MACVALUE
  1440.                 if (*rp == MACVALUE) {
  1441.                     extern char *macvalue();
  1442.                     char *p = macvalue(rp[1], CurEnv);
  1443.                     if (tTd(21, 2))
  1444.                         printf("expanding runtime macro '%c' to \"%s\"\n",
  1445.                             rp[1], p ? p : "(null)");
  1446.                     if (p)
  1447.                         *avp++ = p;
  1448.                 }
  1449.                 else
  1450. #endif MACVALUE
  1451.                     *avp++ = rp;
  1452. d722 1
  1453. a722 1
  1454.             char **hbrvp, **ubrvp;
  1455. d726 1
  1456. a726 1
  1457.             char hbuf[MAXNAME + 1], ubuf[MAXNAME + 1];
  1458. a728 2
  1459.             bool match, defaultpart;
  1460.             char begintype, db;
  1461. d731 1
  1462. a731 1
  1463.             if (**rvp != HOSTBEGIN && **rvp != KEYBEGIN)
  1464. d735 1
  1465. a735 1
  1466.             **  Got a hostname or database lookup.
  1467. a739 1
  1468.             begintype = **rvp;
  1469. a740 1
  1470.             ubrvp = NULL;
  1471. a741 6
  1472.             /* read database name if that's what we're up for */
  1473.             if (begintype == KEYBEGIN) {
  1474.                 if (*++rvp != NULL)
  1475.                     db = **rvp;
  1476.             }
  1477.  
  1478. d743 1
  1479. a743 3
  1480.             if (begintype == HOSTBEGIN)
  1481.                 while (*++rvp != NULL && **rvp != HOSTEND &&
  1482.                    **rvp != CANONUSER)
  1483. a744 13
  1484.             else
  1485.                 while (*++rvp != NULL && **rvp != KEYEND &&
  1486.                    **rvp != CANONHOST && **rvp != CANONUSER)
  1487.                     continue;
  1488.             /* got a sprintf argument? */
  1489.             if (**rvp == CANONHOST) {
  1490.                 *rvp = NULL;
  1491.                 ubrvp = rvp+1;
  1492.                 while (*++rvp != NULL && **rvp != KEYEND &&
  1493.                     **rvp != CANONUSER)
  1494.                     continue;
  1495.             }
  1496.             defaultpart = **rvp == CANONUSER;
  1497. d752 5
  1498. a756 19
  1499.             /* Look it up (lowercase version) */
  1500.             cataddr(hbrvp + (begintype == HOSTBEGIN ? 1 : 2),
  1501.                 hbuf, sizeof hbuf);
  1502.             if (begintype == HOSTBEGIN)
  1503.                 match = maphostname(hbuf, sizeof hbuf);
  1504.             else
  1505.             {
  1506.                 if (ubrvp == NULL) {
  1507.                     /* no sprintf argument part */
  1508.                     match = mapkey(db, hbuf, sizeof hbuf, NULL);
  1509.                 }
  1510.                 else
  1511.                 {
  1512.                     cataddr(ubrvp, ubuf, sizeof ubuf);
  1513.                     match = mapkey(db, hbuf, sizeof hbuf, ubuf);
  1514.                 }
  1515.             }
  1516.             if (match || !defaultpart) {
  1517.                 /* scan the new route/host name */
  1518. d758 1
  1519. a758 1
  1520.                 xpvp = prescan(hbuf, '\0', pvpbuf);
  1521. d760 3
  1522. a762 6
  1523.                 if (xpvp == NULL) {
  1524.                     syserr("rewrite: cannot prescan %s: %s", 
  1525.                         begintype == HOSTBEGIN ?
  1526.                         "new hostname" :
  1527.                         "dbm lookup result",
  1528.                         hbuf);
  1529. d767 2
  1530. a768 1
  1531.                 for (avp = hbrvp; *xpvp != NULL; xpvp++) {
  1532. a772 3
  1533.             }
  1534.             else
  1535.                 avp = hbrvp;
  1536. d775 1
  1537. a775 10
  1538.             rvp = avp - 1;
  1539.             for (xpvp = pvpb1; *xpvp != NULL; xpvp++) {
  1540.                 if (defaultpart && (begintype == HOSTBEGIN ?
  1541.                     **xpvp == HOSTEND :
  1542.                     **xpvp == KEYEND)) {
  1543.                     defaultpart = FALSE;
  1544.                     rvp = avp - 1;
  1545.                 }
  1546.                 else if (!defaultpart || !match)
  1547.                     *avp++ = *xpvp;
  1548. a777 2
  1549.             }
  1550.             *avp++ = NULL;
  1551. d779 1
  1552. a779 1
  1553.             /*break;*/
  1554. a783 1
  1555.         **  Then copy vector back into original space.
  1556. d786 10
  1557. a795 3
  1558.         callsubr(npvp);
  1559.  
  1560.         for (avp = npvp; *avp++ != NULL;);
  1561. d798 1
  1562. a798 1
  1563.  
  1564. d802 1
  1565. a802 1
  1566.             printcav(pvp);
  1567. d809 1
  1568. a809 1
  1569.         printcav(pvp);
  1570. a812 46
  1571. **  CALLSUBR -- call subroutines in rewrite vector
  1572. **
  1573. **    Parameters:
  1574. **        pvp -- pointer to token vector.
  1575. **
  1576. **    Returns:
  1577. **        none.
  1578. **
  1579. **    Side Effects:
  1580. **        pvp is modified.
  1581. */
  1582.  
  1583. callsubr(pvp)
  1584.     char **pvp;
  1585. {
  1586.     char **rvp;
  1587.     int subr;
  1588.  
  1589.     for (; *pvp != NULL; pvp++)
  1590.         if (**pvp == CALLSUBR) {
  1591.             subr = atoi(pvp[1]);
  1592.  
  1593.             if (tTd(21, 3))
  1594.                 printf("-----callsubr %d\n", subr);
  1595.  
  1596.             /*
  1597.             **  Take care of possible inner calls.
  1598.             */
  1599.             callsubr(pvp+2);
  1600.  
  1601.             /*
  1602.             **  Move vector up over calling opcode.
  1603.             */
  1604.             for (rvp = pvp+2; *rvp != NULL; rvp++)
  1605.                 rvp[-2] = rvp[0];
  1606.             rvp[-2] = NULL;
  1607.  
  1608.             /*
  1609.             **  Call inferior ruleset.
  1610.             */
  1611.             rewrite(pvp, subr);
  1612.  
  1613.             break;
  1614.         }
  1615. }
  1616. /*
  1617. d880 5
  1618. a884 2
  1619.     if (**++tv != CANONHOST) {
  1620.         if (!bitnset(M_LOCAL, m->m_flags)) {
  1621. a887 5
  1622.         else
  1623.             a->q_host = NULL;
  1624.     }
  1625.     else
  1626.     {
  1627. d889 2
  1628. a890 2
  1629.         while (*++tv != NULL && **tv != CANONUSER)
  1630.             (void) strcat(buf, *tv);
  1631. d893 2
  1632. a902 3
  1633.     /* define tohost before running mailer rulesets */
  1634.     define('h', a->q_host, CurEnv);
  1635.  
  1636. d905 2
  1637. a906 2
  1638.     if (m->m_re_rwset > 0)
  1639.         rewrite(tv, m->m_re_rwset);
  1640. d987 1
  1641. a987 1
  1642.     if (strcasecmp(a->q_user, b->q_user))
  1643. d997 1
  1644. a997 1
  1645.     if (strcasecmp(a->q_host, b->q_host))
  1646. a1053 2
  1647. **        headeraddress -- if set, use header specific rewriting
  1648. **            rulesets and uurelativize if M_RELATIVIZE is set.
  1649. d1068 1
  1650. a1068 1
  1651. remotename(name, m, senderaddress, canonical, headeraddress)
  1652. a1072 1
  1653.     bool headeraddress;
  1654. d1088 1
  1655. a1088 3
  1656.     if ((senderaddress ?
  1657.          (headeraddress ? m->m_sh_rwset : m->m_se_rwset) :
  1658.          (headeraddress ? m->m_rh_rwset : m->m_re_rwset)) < 0)
  1659. d1134 2
  1660. a1135 3
  1661.     **    Rewrite using ruleset 1 or 2 for envelope addresses and
  1662.     **    5 or 6 for header addresses depending on whether this
  1663.     **    is a sender address or not.
  1664. d1139 1
  1665. a1139 7
  1666.     if (senderaddress) {
  1667.         if (headeraddress) {
  1668.             rewrite(pvp, SplitRewriting ? 5 : 1);
  1669.             if (m->m_sh_rwset > 0)
  1670.                 rewrite(pvp, m->m_sh_rwset);
  1671.         }
  1672.         else
  1673. d1142 2
  1674. a1143 2
  1675.             if (m->m_se_rwset > 0)
  1676.                 rewrite(pvp, m->m_se_rwset);
  1677. a1144 1
  1678.     }
  1679. a1146 7
  1680.         if (headeraddress) {
  1681.             rewrite(pvp, SplitRewriting ? 6 : 2);
  1682.             if (m->m_rh_rwset > 0)
  1683.                 rewrite(pvp, m->m_rh_rwset);
  1684.         }
  1685.         else
  1686.         {
  1687. d1148 2
  1688. a1149 2
  1689.             if (m->m_re_rwset > 0)
  1690.                 rewrite(pvp, m->m_re_rwset);
  1691. a1150 1
  1692.     }
  1693. a1161 8
  1694.     **  Check if we're supposed to do make the address
  1695.     **  UUCP !-relative to the rcpt host vs ourselves.
  1696.     */
  1697.  
  1698.     if (headeraddress && bitnset(M_RELATIVIZE, m->m_flags))
  1699.         uurelativize("\001k", "\001h", pvp);
  1700.  
  1701.     /*
  1702. a1172 67
  1703. }
  1704. /*
  1705. **  UURELATIVIZE -- Make an address !-relative to recipient/sender nodes
  1706. **
  1707. **    Parameters:
  1708. **        from -- the sending node (usually "$k" or "$w")
  1709. **        to -- the receiving node (usually "$h")
  1710. **        pvp -- address vector
  1711. **
  1712. **    Returns:
  1713. **        none.
  1714. **
  1715. **    Side Effects:
  1716. **        The pvp is rewritten to be relative the "to" node
  1717. **        wrt the "from" node.  In other words, if the pvp
  1718. **        is headed by "to!" that part is stripped; otherwise
  1719. **        "from!" is prepended.  Exception: "to!user" addresses
  1720. **        with no '!'s in the user part are sent as is.
  1721. **
  1722. **    Bugs:
  1723. **        The pvp may overflow, but we don't catch it.
  1724. */
  1725.  
  1726. uurelativize(from, to, pvp)
  1727.     char *from, *to;
  1728.     char **pvp;
  1729. {
  1730.     register char **pxp = pvp;
  1731.     char expfrom[MAXNAME], expto[MAXNAME];
  1732.  
  1733.     expand(from, expfrom, &expfrom[sizeof expfrom - 1], CurEnv);
  1734.     expand(to, expto, &expto[sizeof expto - 1], CurEnv);
  1735.  
  1736.     /*
  1737.      * supposing that we've got something, should
  1738.      * we add "from!" or remove "to!"?
  1739.      */
  1740.     if (pvp[0] != NULL)
  1741.         if (pvp[1] == NULL || strcmp(pvp[1], "!") != 0 ||
  1742.             /*strcasecmp?*/ strcmp(pvp[0], expto) != 0) {
  1743.             /* either local name, no UUCP address, */
  1744.             /* or not to "to!" ==> prepend address with "from!" */
  1745.  
  1746.             /* already there? */
  1747.             if (pvp[1] == NULL || strcmp(pvp[1], "!") != 0 ||
  1748.                 /*strcasecmp?*/ strcmp(pvp[0], expfrom) != 0) {
  1749.  
  1750.                 /* no, put it there */
  1751.                 while (*pxp != NULL)
  1752.                     pxp++;
  1753.                 do
  1754.                     pxp[2] = *pxp;
  1755.                 while (pxp-- != pvp);
  1756.                 pvp[0] = newstr(expfrom);
  1757.                 pvp[1] = "!";
  1758.             }
  1759.         }
  1760.         else
  1761.         {
  1762.             /* address is to "to!" -- remove if not "to!user" */
  1763.             for (pxp = &pvp[2];
  1764.                 *pxp != NULL && strcmp(*pxp, "!") != 0;
  1765.                 pxp++);
  1766.                 if (*pxp != NULL)
  1767.                     for (pxp = pvp; *pxp != NULL; pxp++)
  1768.                         *pxp = pxp[2];
  1769.         }
  1770. @
  1771.  
  1772.  
  1773. 5.13.0.2
  1774. log
  1775. @Date: Fri, 6 Jul 90 19:06:37 -0500
  1776. From: Neil Rickert <rickert@@cs.niu.edu>
  1777. To: Paul-Pomes@@uiuc.edu
  1778. Subject: Sendmail patches.
  1779. Cc: mdb@@kosciusko.esd.3com.com
  1780.  
  1781.  The Sendmail.mc patches effect the UUCP mailer and the UUCP-A mailer.
  1782.  
  1783.  First, for the UUCP mailer.  The main effect is that a header address
  1784. of 'user@@full.domain.name' will now go out as 
  1785.  'full.domain.name!user'.  Before this patch it used to go out as
  1786.  'myuucpname!full.domain.name!user'.
  1787.  
  1788.  The patch defines ruleset 13 for the UUCP header addresses.
  1789.  
  1790.  The main purpose is to improve mail headers for MX addresses relayed through
  1791.  UUCP hosts.  It will not effect normal UUCP addresses, nor domain addresses
  1792.  which are translated to UUCP addresses in uucpxtable.
  1793.  
  1794.  -
  1795.  
  1796.  The patch for the UUCP-A mailer consists of changes to ruleset S21.
  1797. It requires the code patch to parseaddr.c to be effective.  (If the patch
  1798. is installed without the code change there are no bad effects - it is just
  1799. not fully functional).
  1800.  
  1801.  The change is as follows:
  1802.  
  1803.    If a local UUCP neighbour address of 'user@@uuhost.UUCP' is in a header
  1804. for the TCP mailers of the UUCP-A mailer, the address previously was sent
  1805. out as  'user%uuhost.UUCP@@our.domain.name'.  This can result in problems if
  1806. the recipient is using a route stripping algorithm similar to that in the
  1807. IDA package, for the recipient mailer will reduce the address to
  1808. 'user@@uuhost.UUCP', and this may prevent replies if uuhost is not on the uumap.
  1809.  
  1810.    With the change, the address will instead be sent out as
  1811.     'uuhost!user@@our.domain.name' which is less likely to be stripped with
  1812. route stripping algorithms, since the 'uuhost' domain is not qualified.
  1813. A second change occurs only for the UUCP-A mailer.  Previously an address
  1814. 'user@@uuhost.UUCP' was sent as 'user%uuhost.UUCP@@our.domain.name' or as
  1815. 'uuhost!user@@our.domain.name' even if the recipient host is uuhost itself.
  1816. With this change, if the recipient domain is uuhost itself, the address
  1817. will remain as 'user@@uuhost.UUCP' without the extraneous routing.
  1818.  
  1819.   It is only this latter portion, for UUCP-A, which will not do anything unless
  1820. the code changes are also made.
  1821.  
  1822. ------------------------------------
  1823.  
  1824.  The code patch to parseaddr.c is to allow $&x to appear on the left hand side
  1825. of a rewriting rule.  In the previous behaviour, $&x could be used on the RHS
  1826. of a rule, for delayed evaluation of the macro $x.  But when used on the
  1827. left hand side it would never match anything.  With the patch $&x also allows
  1828. delayed evaluation as a left matching string, and the matched value - possibly
  1829. including null - is assigned to a $n variable.
  1830. @
  1831. text
  1832. @a638 24
  1833. #ifdef MACVALUE
  1834.               case MACVALUE:
  1835.                 {
  1836.                 extern char *macvalue();
  1837.                 char *p = macvalue(rp[1], CurEnv);
  1838.                 if (tTd(21, 2))
  1839.                     printf("expanding runtime macro '%c' to \"%s\"\n",
  1840.                         rp[1], p ? p : "(null)");
  1841.                 oldavp = avp;
  1842.                 if (p) while (*p) {
  1843.                     if (*avp == NULL ||
  1844.                        strncasecmp(p,*avp,strlen(*avp))) {
  1845.                         avp = oldavp;
  1846.                         goto backup;
  1847.                        }
  1848.                     p += strlen(*avp++);
  1849.                     }
  1850.                 mlp->first = oldavp;
  1851.                 mlp->last = avp -1;
  1852.                 }
  1853.                 mlp++;
  1854.                 break;
  1855. #endif MACVALUE
  1856.  
  1857. @
  1858.  
  1859.  
  1860. 5.13.0.3
  1861. log
  1862. @Corrected use of mapkey return value.
  1863. @
  1864. text
  1865. @d913 1
  1866. a913 1
  1867.                     match = (mapkey(db, hbuf, sizeof hbuf, NULL) != NULL);
  1868. d918 1
  1869. a918 1
  1870.                     match = (mapkey(db, hbuf, sizeof hbuf, ubuf) != NULL);
  1871. @
  1872.  
  1873.  
  1874. 5.13.0.4
  1875. log
  1876. @Bruce Lilly (bruce%balilly@@sonyd1.broadcast.sony.com) fix for not mangling
  1877. named lists.
  1878. @
  1879. text
  1880. @a369 3
  1881.             if (c == ';') /* semicolons are not tokens */
  1882.                 c = NOCHAR;
  1883.  
  1884. d857 1
  1885. a857 2
  1886.             char begintype;
  1887.             char db = '\0';
  1888. @
  1889.  
  1890.  
  1891. 5.13.0.5
  1892. log
  1893. @Add some (char) casts to cheer up gcc.
  1894. @
  1895. text
  1896. @d540 1
  1897. a540 1
  1898.             (void) strncat(buf, *pvp++, sizeof buf);
  1899. d612 1
  1900. a612 1
  1901.                 *tokbuf = (char) NULL;
  1902. d618 1
  1903. a618 1
  1904.                     (void) strcat(tokbuf, *avp++);
  1905. d691 1
  1906. a691 1
  1907.                     *tokbuf = (char) NULL;
  1908. d694 1
  1909. a694 1
  1910.                         (void) strcat(tokbuf, *avp);
  1911. d703 1
  1912. a703 1
  1913.                         (void) strcat(tokbuf, *avp++);
  1914. @
  1915.  
  1916.  
  1917. 5.13.0.6
  1918. log
  1919. @From: forys@@snake.utah.edu (Jeff Forys)
  1920. Newsgroups: comp.mail.sendmail
  1921. Date: 10 Nov 90 01:48:40 MST
  1922. Organization: University of Utah CS Dept
  1923. Subject: Sendmail 5.65 can loop on certain addresses +FIX
  1924.  
  1925. Index:    usr.lib/sendmail/src/parseaddr.c 4.3BSD
  1926.  
  1927. This applies to all known versions of sendmail (through "5.65").
  1928.  
  1929. Description:
  1930.     Sendmail reserves characters in the range 020 - 036 for coding
  1931.     its rewrite rules.  If one of these characters shows up in an
  1932.     address, the results are unpredictable (from a user's point of
  1933.     view).  Specifically, an address containing a "replacement on
  1934.     RHS" rule can cause sendmail to go into an infinite loop while
  1935.     processing various rewrite rules.
  1936.  
  1937.     I suppose this could be used for a denial-of-service attack;
  1938.     if an evil-minded person fired off a bunch of these in your
  1939.     direction, you would end up with an equal number of sendmail
  1940.     processes churning endlessly away on your CPU.  Of course,
  1941.     whence such an "attack" originates would be painfully obvious!
  1942. @
  1943. text
  1944. @a88 3
  1945.     if (invalidaddr(addr))
  1946.         return (NULL);
  1947.  
  1948. a189 39
  1949. }
  1950. /*
  1951. **  INVALIDADDR -- check an address string for invalid control characters.
  1952. **
  1953. **    Parameters:
  1954. **        addr -- address string to be checked.
  1955. **
  1956. **    Returns:
  1957. **        TRUE if address string could cause problems, FALSE o/w.
  1958. **
  1959. **    Side Effects:
  1960. **        ExitStat may be changed and an error message generated.
  1961. */
  1962.  
  1963. invalidaddr(addr)
  1964.     char *addr;
  1965. {
  1966.     register char *cp;
  1967.     extern int errno;
  1968.  
  1969.     /* make sure error messages don't have garbage on them */
  1970.     errno = 0;
  1971.  
  1972.     /*
  1973.     ** Sendmail reserves characters 020 - 036 for rewriting rules
  1974.     ** which can cause havoc (e.g. infinite rewriting loops) if
  1975.     ** one shows up at the wrong time.  If any of these characters
  1976.     ** appear in an address, the address is deemed "invalid" and
  1977.     ** an error message is generated.
  1978.     */
  1979.  
  1980.     for (cp = addr; *cp; cp++)
  1981.         if ((*cp >= MATCHZANY && *cp <= HOSTEND) || *cp == '\001')
  1982.         {
  1983.             setstat(EX_USAGE);
  1984.             usrerr("address contained invalid control char(s)");
  1985.             return (TRUE);
  1986.         }
  1987.     return (FALSE);
  1988. @
  1989.  
  1990.  
  1991. 5.13.0.7
  1992. log
  1993. @Commented out tokens following #endif statements.
  1994. @
  1995. text
  1996. @d25 1
  1997. a25 1
  1998. #include "sendmail.h"
  1999. d493 1
  2000. a493 1
  2001. #endif /* MACVALUE */
  2002. d706 1
  2003. a706 1
  2004. #endif /* MACVALUE */
  2005. d882 1
  2006. a882 1
  2007. #endif /* MACVALUE */
  2008. @
  2009.  
  2010.  
  2011. 5.13.0.8
  2012. log
  2013. @Deleted un-needed initialization.
  2014. @
  2015. text
  2016. @d1207 1
  2017. a1207 1
  2018.     bool natomtok;
  2019. @
  2020.  
  2021.  
  2022. 5.13.0.9
  2023. log
  2024. @Added char *mapkey() declaration.
  2025. @
  2026. text
  2027. @d904 1
  2028. a904 1
  2029.             extern char *DelimChar, *mapkey();
  2030. @
  2031.  
  2032.  
  2033. 5.13.0.10
  2034. log
  2035. @Replaced an occurence of struct mailer with MAILER.
  2036. @
  2037. text
  2038. @a553 1
  2039. static
  2040. d1343 1
  2041. a1343 1
  2042.     MAILER *m;
  2043. @
  2044.  
  2045.  
  2046. 5.13.0.11
  2047. log
  2048. @Added static keyword to declaration for toktype(), _rewrite(), callsubr(),
  2049. uurelativize() and buildaddr().
  2050. @
  2051. text
  2052. @a26 2
  2053. static toktype(), _rewrite(), callsubr(), uurelativize();
  2054.  
  2055. d79 1
  2056. a79 1
  2057.     static ADDRESS *buildaddr();
  2058. a475 1
  2059. static
  2060. a1047 1
  2061. static
  2062. d1097 1
  2063. a1097 1
  2064. static ADDRESS *
  2065. a1496 1
  2066. static
  2067. @
  2068.  
  2069.  
  2070. 5.13.0.12
  2071. log
  2072. @ANSIfied.
  2073. @
  2074. text
  2075. @d27 1
  2076. a27 17
  2077. #ifdef __STDC__
  2078. # ifdef    CC_WONT_PROMOTE
  2079. static toktype(char);
  2080. # else    /* !CC_WONT_PROMOTE */
  2081. static toktype(int);                /* char -> int */
  2082. # endif    /* CC_WONT_PROMOTE */
  2083. static void _rewrite(char **, int);
  2084. static void callsubr(char **);
  2085. static ADDRESS * buildaddr(char **, ADDRESS *);
  2086. static void uurelativize(const char *, const char *, char **);
  2087. #else /* !__STDC__ */
  2088. static toktype();
  2089. static void _rewrite();
  2090. static void callsubr();
  2091. static ADDRESS * buildaddr();
  2092. static void uurelativize();
  2093. #endif /* __STDC__ */
  2094. a28 2
  2095. char    *DelimChar;        /* set to point to the delimiter */
  2096.  
  2097. d80 2
  2098. d87 1
  2099. a87 1
  2100.     CurEnv->e_to = (char *)addr;
  2101. d133 1
  2102. a187 1
  2103. void
  2104. a208 1
  2105. bool
  2106. d210 1
  2107. a210 1
  2108.     const char *addr;
  2109. d212 1
  2110. a212 1
  2111.     register const char *cp;
  2112. d294 2
  2113. a548 1
  2114. void
  2115. d557 1
  2116. a557 1
  2117. static void
  2118. d691 1
  2119. a692 1
  2120.  
  2121. d877 1
  2122. a878 1
  2123.  
  2124. d908 1
  2125. d1051 1
  2126. a1051 1
  2127. static void
  2128. d1053 1
  2129. a1053 1
  2130.     char **pvp;
  2131. a1205 1
  2132. void
  2133. a1291 1
  2134. void
  2135. d1355 1
  2136. d1360 2
  2137. d1501 1
  2138. a1501 1
  2139. static void
  2140. d1503 1
  2141. a1503 1
  2142.     const char *from, *to;
  2143. @
  2144.  
  2145.  
  2146. 5.13.0.13
  2147. log
  2148. @Added RCS ID string
  2149. @
  2150. text
  2151. @a22 1
  2152. static char  rcsid[] = "@@(#)$Id$";
  2153. @
  2154.  
  2155.  
  2156. 5.13.0.14
  2157. log
  2158. @Minor cleanups.
  2159. @
  2160. text
  2161. @d23 1
  2162. a23 1
  2163. static char  rcsid[] = "@@(#)$Id: parseaddr.c,v 5.13.0.13 1991/04/05 14:55:15 paul Exp paul $";
  2164. d598 1
  2165. a598 2
  2166.     if (++nrw > 100)
  2167.     {
  2168. d628 1
  2169. a628 2
  2170.             if (nloops++ > 200)
  2171.             {
  2172. d677 1
  2173. a677 2
  2174.                     if (*avp == NULL)
  2175.                     {
  2176. d679 1
  2177. a679 1
  2178.                         goto backup;
  2179. d707 1
  2180. a707 1
  2181.                 {
  2182. d714 1
  2183. a714 2
  2184.                 if (p) while (*p)
  2185.                 {
  2186. d716 1
  2187. a716 2
  2188.                        strncasecmp(p,*avp,strlen(*avp)))
  2189.                     {
  2190. d719 2
  2191. a721 2
  2192.                     p += strlen(*avp++);
  2193.                 }
  2194. d724 3
  2195. a726 3
  2196.                 }
  2197.             mlp++;
  2198.             break;
  2199. d746 1
  2200. a746 2
  2201.                 if (*rp == MATCHCLASS)
  2202.                 {
  2203. d760 1
  2204. a760 2
  2205.                         if (*avp == NULL)
  2206.                         {
  2207. d813 1
  2208. a813 2
  2209.         if (nmatches++ > 200)
  2210.         {
  2211. d893 1
  2212. a893 2
  2213.                 if (*rp == MACVALUE)
  2214.                 {
  2215. d940 1
  2216. a940 2
  2217.             if (begintype == KEYBEGIN)
  2218.             {
  2219. d955 1
  2220. a955 2
  2221.             if (**rvp == CANONHOST)
  2222.             {
  2223. d977 1
  2224. a977 2
  2225.                 if (ubrvp == NULL)
  2226.                 {
  2227. d987 1
  2228. a987 2
  2229.             if (match || !defaultpart)
  2230.             {
  2231. d992 1
  2232. a992 2
  2233.                 if (xpvp == NULL)
  2234.                 {
  2235. d1002 1
  2236. a1002 2
  2237.                 for (avp = hbrvp; *xpvp != NULL; xpvp++)
  2238.                 {
  2239. d1006 1
  2240. a1006 1
  2241.                 }
  2242. d1013 1
  2243. a1013 2
  2244.             for (xpvp = pvpb1; *xpvp != NULL; xpvp++)
  2245.             {
  2246. d1016 1
  2247. a1016 2
  2248.                     **xpvp == KEYEND))
  2249.                 {
  2250. d1075 1
  2251. a1075 2
  2252.         if (**pvp == CALLSUBR)
  2253.         {
  2254. d1169 2
  2255. a1170 4
  2256.     if (**++tv != CANONHOST)
  2257.     {
  2258.         if (!bitnset(M_LOCAL, m->m_flags))
  2259.         {
  2260. d1436 2
  2261. a1437 4
  2262.     if (senderaddress)
  2263.     {
  2264.         if (headeraddress)
  2265.         {
  2266. d1451 1
  2267. a1451 2
  2268.         if (headeraddress)
  2269.         {
  2270. d1533 1
  2271. a1533 2
  2272.             /*strcasecmp?*/ strcmp(pvp[0], expto) != 0)
  2273.         {
  2274. d1539 1
  2275. a1539 2
  2276.                 /*strcasecmp?*/ strcmp(pvp[0], expfrom) != 0)
  2277.             {
  2278. @
  2279.  
  2280.  
  2281. 5.13.0.15
  2282. log
  2283. @Fix problem with quoted characters.
  2284. @
  2285. text
  2286. @d23 1
  2287. a23 1
  2288. static char  rcsid[] = "@@(#)$Id: parseaddr.c,v 5.13.0.14 1991/04/11 20:31:35 paul Exp paul $";
  2289. d393 1
  2290. a393 1
  2291.             if (state == QST)
  2292. @
  2293.  
  2294.  
  2295. 5.13.0.16
  2296. log
  2297. @System 5 and general improvement patches contributed by Bruce Lilly
  2298. (bruce%balilly@@broadcast.sony.com).
  2299. @
  2300. text
  2301. @d22 2
  2302. a23 2
  2303. static char sccsid[] = "@@(#)parseaddr.c    5.13 (Berkeley) 6/1/90    %I% local";
  2304. static char  rcsid[] = "@@(#)$Id: parseaddr.c,v 5.13.0.15 1991/04/25 22:19:43 paul Exp paul $";
  2305. d30 1
  2306. a30 1
  2307. static int toktype(char);
  2308. d32 1
  2309. a32 1
  2310. static int toktype(int);                /* char -> int */
  2311. d39 1
  2312. a39 1
  2313. static int toktype();
  2314. d494 1
  2315. a494 1
  2316. static int
  2317. @
  2318.  
  2319.  
  2320. 5.13.0.17
  2321. log
  2322. @Added LHS map lookup ($%Y and $^Y) adapted from Simon Gerraty's patch
  2323. (sjg@@melb.bull.oz.au).
  2324. @
  2325. text
  2326. @d22 2
  2327. a23 2
  2328. static char sccsid[] = "@@(#)parseaddr.c    5.13 (Berkeley) 6/1/90";
  2329. static char  rcsid[] = "@@(#)$Id: parseaddr.c,v 5.13.0.16 1991/05/18 17:31:23 paul Exp paul $";
  2330. d507 1
  2331. a507 2
  2332.     if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS ||
  2333.         c == MATCHMAP   || c == MATCHNMAP)
  2334. a692 32
  2335.               case MATCHMAP:
  2336.                 /* match any token in a DBM map */
  2337.                 /* handles multi-token class matches */
  2338.                 oldavp = avp;
  2339.                 *tokbuf = NULL;
  2340.                 do {
  2341.                     if (*avp == NULL)
  2342.                     {
  2343.                         avp = oldavp;
  2344.                         goto backup;
  2345.                     }
  2346.                     (void) strcat(tokbuf, *avp++);
  2347.                 } while (mapkey(rp[1], tokbuf, sizeof(tokbuf)-1,                            NULL) == NULL);
  2348.                 mlp->first = oldavp;
  2349.                 mlp->last = avp-1;
  2350.                 mlp++;
  2351.                 break;
  2352.  
  2353.               case MATCHNMAP:
  2354.                 /* match any token not in a DBM map */
  2355.                 if ((rp = mapkey(rp[1], ap, 0, NULL)) != NULL)
  2356.                 {
  2357.                     free(rp);
  2358.                     goto backup;
  2359.                 }
  2360.  
  2361.                 /* match exactly one token */
  2362.                 mlp->first = avp;
  2363.                 mlp->last = avp++;
  2364.                 mlp++;
  2365.                 break;
  2366.  
  2367. a984 1
  2368. #ifdef VMUNIX
  2369. a985 3
  2370. #else /* !VMUNIX */
  2371.                 match = FALSE;
  2372. #endif /* VMUNIX */
  2373. a1161 7
  2374.         buf[0] = '\0';
  2375.         for (; (*tv != NULL) && (**tv != CANONUSER); tv++)
  2376.         {
  2377.             if (buf[0] != '\0')
  2378.                 (void) strcat(buf, " ");
  2379.             (void) strcat(buf, *tv);
  2380.         }
  2381. d1164 1
  2382. @
  2383.  
  2384.  
  2385. 5.13.0.18
  2386. log
  2387. @Added missing (char) cast.
  2388. @
  2389. text
  2390. @d23 1
  2391. a23 1
  2392. static char  rcsid[] = "@@(#)$Id: parseaddr.c,v 5.13.0.17 1991/06/24 14:24:26 paul Exp paul $";
  2393. d698 1
  2394. a698 1
  2395.                 *tokbuf = (char) NULL;
  2396. @
  2397.