"Fossies" - the Fresh Open Source Software Archive

Member "sendmail-8.15.2/sendmail/macro.c" (5 Mar 2014, 14731 Bytes) of package /linux/misc/sendmail.8.15.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "macro.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 1998-2001, 2003, 2006, 2007 Proofpoint, Inc. and its suppliers.
    3  *  All rights reserved.
    4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
    5  * Copyright (c) 1988, 1993
    6  *  The Regents of the University of California.  All rights reserved.
    7  *
    8  * By using this file, you agree to the terms and conditions set
    9  * forth in the LICENSE file which can be found at the top level of
   10  * the sendmail distribution.
   11  *
   12  */
   13 
   14 #include <sendmail.h>
   15 
   16 SM_RCSID("@(#)$Id: macro.c,v 8.108 2013-11-22 20:51:55 ca Exp $")
   17 
   18 #include <sm/sendmail.h>
   19 #if MAXMACROID != (BITMAPBITS - 1)
   20     ERROR Read the comment in conf.h
   21 #endif /* MAXMACROID != (BITMAPBITS - 1) */
   22 
   23 static char *MacroName[MAXMACROID + 1]; /* macro id to name table */
   24 
   25 /*
   26 **  Codes for long named macros.
   27 **  See also macname():
   28     * if not ASCII printable, look up the name *
   29     if (n <= 0x20 || n > 0x7f)
   30 **  First use 1 to NEXTMACROID_L, then use NEXTMACROID_H to MAXMACROID.
   31 */
   32 
   33 #define NEXTMACROID_L 037
   34 #define NEXTMACROID_H 0240
   35 
   36 #if _FFR_MORE_MACROS
   37 /* table for next id in non-printable ASCII range: disallow some value */
   38 static int NextMIdTable[] =
   39 {
   40     /*  0  nul */    1,
   41     /*  1  soh */    2,
   42     /*  2  stx */    3,
   43     /*  3  etx */    4,
   44     /*  4  eot */    5,
   45     /*  5  enq */    6,
   46     /*  6  ack */    7,
   47     /*  7  bel */    8,
   48     /*  8  bs  */   14,
   49     /*  9  ht  */   -1,
   50     /* 10  nl  */   -1,
   51     /* 11  vt  */   -1,
   52     /* 12  np  */   -1,
   53     /* 13  cr  */   -1,
   54     /* 14  so  */   15,
   55     /* 15  si  */   16,
   56     /* 16  dle */   17,
   57     /* 17  dc1 */   18,
   58     /* 18  dc2 */   19,
   59     /* 19  dc3 */   20,
   60     /* 20  dc4 */   21,
   61     /* 21  nak */   22,
   62     /* 22  syn */   23,
   63     /* 23  etb */   24,
   64     /* 24  can */   25,
   65     /* 25  em  */   26,
   66     /* 26  sub */   27,
   67     /* 27  esc */   28,
   68     /* 28  fs  */   29,
   69     /* 29  gs  */   30,
   70     /* 30  rs  */   31,
   71     /* 31  us  */   32,
   72     /* 32  sp  */   -1,
   73 };
   74 
   75 #define NEXTMACROID(mid)    (       \
   76     (mid < NEXTMACROID_L) ? (NextMIdTable[mid]) :   \
   77     ((mid < NEXTMACROID_H) ? NEXTMACROID_H : (mid + 1)))
   78 
   79 int     NextMacroId = 1;    /* codes for long named macros */
   80 /* see sendmail.h: Special characters in rewriting rules. */
   81 #else /* _FFR_MORE_MACROS */
   82 int     NextMacroId = 0240; /* codes for long named macros */
   83 #define NEXTMACROID(mid)    ((mid) + 1)
   84 #endif /* _FFR_MORE_MACROS */
   85 
   86 
   87 /*
   88 **  INITMACROS -- initialize the macro system
   89 **
   90 **  This just involves defining some macros that are actually
   91 **  used internally as metasymbols to be themselves.
   92 **
   93 **  Parameters:
   94 **      none.
   95 **
   96 **  Returns:
   97 **      none.
   98 **
   99 **  Side Effects:
  100 **      initializes several macros to be themselves.
  101 */
  102 
  103 struct metamac  MetaMacros[] =
  104 {
  105     /* LHS pattern matching characters */
  106     { '*', MATCHZANY }, { '+', MATCHANY },  { '-', MATCHONE },
  107     { '=', MATCHCLASS },    { '~', MATCHNCLASS },
  108 
  109     /* these are RHS metasymbols */
  110     { '#', CANONNET },  { '@', CANONHOST }, { ':', CANONUSER },
  111     { '>', CALLSUBR },
  112 
  113     /* the conditional operations */
  114     { '?', CONDIF },    { '|', CONDELSE },  { '.', CONDFI },
  115 
  116     /* the hostname lookup characters */
  117     { '[', HOSTBEGIN }, { ']', HOSTEND },
  118     { '(', LOOKUPBEGIN },   { ')', LOOKUPEND },
  119 
  120     /* miscellaneous control characters */
  121     { '&', MACRODEXPAND },
  122 
  123     { '\0', '\0' }
  124 };
  125 
  126 #define MACBINDING(name, mid) \
  127         stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
  128         MacroName[mid] = name;
  129 
  130 void
  131 initmacros(e)
  132     ENVELOPE *e;
  133 {
  134     struct metamac *m;
  135     int c;
  136     char buf[5];
  137 
  138     for (m = MetaMacros; m->metaname != '\0'; m++)
  139     {
  140         buf[0] = m->metaval;
  141         buf[1] = '\0';
  142         macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
  143     }
  144     buf[0] = MATCHREPL;
  145     buf[2] = '\0';
  146     for (c = '0'; c <= '9'; c++)
  147     {
  148         buf[1] = c;
  149         macdefine(&e->e_macro, A_TEMP, c, buf);
  150     }
  151 
  152     /* set defaults for some macros sendmail will use later */
  153     macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
  154 
  155     /* set up external names for some internal macros */
  156     MACBINDING("opMode", MID_OPMODE);
  157     /*XXX should probably add equivalents for all short macros here XXX*/
  158 }
  159 
  160 /*
  161 **  EXPAND/DOEXPAND -- macro expand a string using $x escapes.
  162 **
  163 **  After expansion, the expansion will be in external form (that is,
  164 **  there will be no sendmail metacharacters and METAQUOTEs will have
  165 **  been stripped out).
  166 **
  167 **  Parameters:
  168 **      s -- the string to expand.
  169 **      buf -- the place to put the expansion.
  170 **      bufsize -- the size of the buffer.
  171 **      explevel -- the depth of expansion (doexpand only)
  172 **      e -- envelope in which to work.
  173 **
  174 **  Returns:
  175 **      none.
  176 **
  177 **  Side Effects:
  178 **      none.
  179 */
  180 
  181 static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *));
  182 
  183 static void
  184 doexpand(s, buf, bufsize, explevel, e)
  185     char *s;
  186     char *buf;
  187     size_t bufsize;
  188     int explevel;
  189     ENVELOPE *e;
  190 {
  191     char *xp;
  192     char *q;
  193     bool skipping;      /* set if conditionally skipping output */
  194     bool recurse;       /* set if recursion required */
  195     size_t i;
  196     int skiplev;        /* skipping nesting level */
  197     int iflev;      /* if nesting level */
  198     bool quotenext;     /* quote the following character */
  199     char xbuf[MACBUFSIZE];
  200 
  201     if (tTd(35, 24))
  202     {
  203         sm_dprintf("expand(");
  204         xputs(sm_debug_file(), s);
  205         sm_dprintf(")\n");
  206     }
  207 
  208     recurse = false;
  209     skipping = false;
  210     skiplev = 0;
  211     iflev = 0;
  212     quotenext = false;
  213     if (s == NULL)
  214         s = "";
  215     for (xp = xbuf; *s != '\0'; s++)
  216     {
  217         int c;
  218 
  219         /*
  220         **  Check for non-ordinary (special?) character.
  221         **  'q' will be the interpolated quantity.
  222         */
  223 
  224         q = NULL;
  225         c = *s & 0377;
  226 
  227         if (quotenext)
  228         {
  229             quotenext = false;
  230             goto simpleinterpolate;
  231         }
  232 
  233         switch (c)
  234         {
  235           case CONDIF:      /* see if var set */
  236             iflev++;
  237             c = *++s & 0377;
  238             if (skipping)
  239                 skiplev++;
  240             else
  241             {
  242                 char *mv;
  243 
  244                 mv = macvalue(c, e);
  245                 skipping = (mv == NULL || *mv == '\0');
  246             }
  247             continue;
  248 
  249           case CONDELSE:    /* change state of skipping */
  250             if (iflev == 0)
  251                 break;  /* XXX: error */
  252             if (skiplev == 0)
  253                 skipping = !skipping;
  254             continue;
  255 
  256           case CONDFI:      /* stop skipping */
  257             if (iflev == 0)
  258                 break;  /* XXX: error */
  259             iflev--;
  260             if (skiplev == 0)
  261                 skipping = false;
  262             if (skipping)
  263                 skiplev--;
  264             continue;
  265 
  266           case MACROEXPAND: /* macro interpolation */
  267             c = bitidx(*++s);
  268             if (c != '\0')
  269                 q = macvalue(c, e);
  270             else
  271             {
  272                 s--;
  273                 q = NULL;
  274             }
  275             if (q == NULL)
  276                 continue;
  277             break;
  278 
  279           case METAQUOTE:
  280             /* next octet completely quoted */
  281             quotenext = true;
  282             break;
  283         }
  284 
  285         /*
  286         **  Interpolate q or output one character
  287         */
  288 
  289   simpleinterpolate:
  290         if (skipping || xp >= &xbuf[sizeof(xbuf) - 1])
  291             continue;
  292         if (q == NULL)
  293             *xp++ = c;
  294         else
  295         {
  296             /* copy to end of q or max space remaining in buf */
  297             bool hiderecurse = false;
  298 
  299             while ((c = *q++) != '\0' &&
  300                 xp < &xbuf[sizeof(xbuf) - 1])
  301             {
  302                 /* check for any sendmail metacharacters */
  303                 if (!hiderecurse && (c & 0340) == 0200)
  304                     recurse = true;
  305                 *xp++ = c;
  306 
  307                 /* give quoted characters a free ride */
  308                 hiderecurse = (c & 0377) == METAQUOTE;
  309             }
  310         }
  311     }
  312     *xp = '\0';
  313 
  314     if (tTd(35, 28))
  315     {
  316         sm_dprintf("expand(%d) ==> ", explevel);
  317         xputs(sm_debug_file(), xbuf);
  318         sm_dprintf("\n");
  319     }
  320 
  321     /* recurse as appropriate */
  322     if (recurse)
  323     {
  324         if (explevel < MaxMacroRecursion)
  325         {
  326             doexpand(xbuf, buf, bufsize, explevel + 1, e);
  327             return;
  328         }
  329         syserr("expand: recursion too deep (%d max)",
  330             MaxMacroRecursion);
  331     }
  332 
  333     /* copy results out */
  334     if (explevel == 0)
  335         (void) sm_strlcpy(buf, xbuf, bufsize);
  336     else
  337     {
  338         /* leave in internal form */
  339         i = xp - xbuf;
  340         if (i >= bufsize)
  341             i = bufsize - 1;
  342         memmove(buf, xbuf, i);
  343         buf[i] = '\0';
  344     }
  345 
  346     if (tTd(35, 24))
  347     {
  348         sm_dprintf("expand ==> ");
  349         xputs(sm_debug_file(), buf);
  350         sm_dprintf("\n");
  351     }
  352 }
  353 
  354 void
  355 expand(s, buf, bufsize, e)
  356     char *s;
  357     char *buf;
  358     size_t bufsize;
  359     ENVELOPE *e;
  360 {
  361     doexpand(s, buf, bufsize, 0, e);
  362 }
  363 
  364 /*
  365 **  MACDEFINE -- bind a macro name to a value
  366 **
  367 **  Set a macro to a value, with fancy storage management.
  368 **  macdefine will make a copy of the value, if required,
  369 **  and will ensure that the storage for the previous value
  370 **  is not leaked.
  371 **
  372 **  Parameters:
  373 **      mac -- Macro table.
  374 **      vclass -- storage class of 'value', ignored if value==NULL.
  375 **          A_HEAP  means that the value was allocated by
  376 **              malloc, and that macdefine owns the storage.
  377 **          A_TEMP  means that value points to temporary storage,
  378 **              and thus macdefine needs to make a copy.
  379 **          A_PERM  means that value points to storage that
  380 **              will remain allocated and unchanged for
  381 **              at least the lifetime of mac.  Use A_PERM if:
  382 **              -- value == NULL,
  383 **              -- value points to a string literal,
  384 **              -- value was allocated from mac->mac_rpool
  385 **                 or (in the case of an envelope macro)
  386 **                 from e->e_rpool,
  387 **              -- in the case of an envelope macro,
  388 **                 value is a string member of the envelope
  389 **                 such as e->e_sender.
  390 **      id -- Macro id.  This is a single character macro name
  391 **          such as 'g', or a value returned by macid().
  392 **      value -- Macro value: either NULL, or a string.
  393 */
  394 
  395 void
  396 #if SM_HEAP_CHECK
  397 macdefine_tagged(mac, vclass, id, value, file, line, grp)
  398 #else /* SM_HEAP_CHECK */
  399 macdefine(mac, vclass, id, value)
  400 #endif /* SM_HEAP_CHECK */
  401     MACROS_T *mac;
  402     ARGCLASS_T vclass;
  403     int id;
  404     char *value;
  405 #if SM_HEAP_CHECK
  406     char *file;
  407     int line;
  408     int grp;
  409 #endif /* SM_HEAP_CHECK */
  410 {
  411     char *newvalue;
  412 
  413     if (id < 0 || id > MAXMACROID)
  414         return;
  415 
  416     if (tTd(35, 9))
  417     {
  418         sm_dprintf("%sdefine(%s as ",
  419             mac->mac_table[id] == NULL ? "" : "re", macname(id));
  420         xputs(sm_debug_file(), value);
  421         sm_dprintf(")\n");
  422     }
  423 
  424     if (mac->mac_rpool == NULL)
  425     {
  426         char *freeit = NULL;
  427 
  428         if (mac->mac_table[id] != NULL &&
  429             bitnset(id, mac->mac_allocated))
  430             freeit = mac->mac_table[id];
  431 
  432         if (value == NULL || vclass == A_HEAP)
  433         {
  434             sm_heap_checkptr_tagged(value, file, line);
  435             newvalue = value;
  436             clrbitn(id, mac->mac_allocated);
  437         }
  438         else
  439         {
  440 #if SM_HEAP_CHECK
  441             newvalue = sm_strdup_tagged_x(value, file, line, 0);
  442 #else /* SM_HEAP_CHECK */
  443             newvalue = sm_strdup_x(value);
  444 #endif /* SM_HEAP_CHECK */
  445             setbitn(id, mac->mac_allocated);
  446         }
  447         mac->mac_table[id] = newvalue;
  448         if (freeit != NULL)
  449             sm_free(freeit);
  450     }
  451     else
  452     {
  453         if (value == NULL || vclass == A_PERM)
  454             newvalue = value;
  455         else
  456             newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
  457         mac->mac_table[id] = newvalue;
  458         if (vclass == A_HEAP)
  459             sm_free(value);
  460     }
  461 
  462 #if _FFR_RESET_MACRO_GLOBALS
  463     switch (id)
  464     {
  465       case 'j':
  466         PSTRSET(MyHostName, value);
  467         break;
  468     }
  469 #endif /* _FFR_RESET_MACRO_GLOBALS */
  470 }
  471 
  472 /*
  473 **  MACSET -- set a named macro to a value (low level)
  474 **
  475 **  No fancy storage management; the caller takes full responsibility.
  476 **  Often used with macget; see also macdefine.
  477 **
  478 **  Parameters:
  479 **      mac -- Macro table.
  480 **      i -- Macro name, specified as an integer offset.
  481 **      value -- Macro value: either NULL, or a string.
  482 */
  483 
  484 void
  485 macset(mac, i, value)
  486     MACROS_T *mac;
  487     int i;
  488     char *value;
  489 {
  490     if (i < 0 || i > MAXMACROID)
  491         return;
  492 
  493     if (tTd(35, 9))
  494     {
  495         sm_dprintf("macset(%s as ", macname(i));
  496         xputs(sm_debug_file(), value);
  497         sm_dprintf(")\n");
  498     }
  499     mac->mac_table[i] = value;
  500 }
  501 
  502 /*
  503 **  MACVALUE -- return uninterpreted value of a macro.
  504 **
  505 **  Does fancy path searching.
  506 **  The low level counterpart is macget.
  507 **
  508 **  Parameters:
  509 **      n -- the name of the macro.
  510 **      e -- envelope in which to start looking for the macro.
  511 **
  512 **  Returns:
  513 **      The value of n.
  514 **
  515 **  Side Effects:
  516 **      none.
  517 */
  518 
  519 char *
  520 macvalue(n, e)
  521     int n;
  522     ENVELOPE *e;
  523 {
  524     n = bitidx(n);
  525     if (e != NULL && e->e_mci != NULL)
  526     {
  527         char *p = e->e_mci->mci_macro.mac_table[n];
  528 
  529         if (p != NULL)
  530             return p;
  531     }
  532     while (e != NULL)
  533     {
  534         char *p = e->e_macro.mac_table[n];
  535 
  536         if (p != NULL)
  537             return p;
  538         if (e == e->e_parent)
  539             break;
  540         e = e->e_parent;
  541     }
  542     return GlobalMacros.mac_table[n];
  543 }
  544 
  545 /*
  546 **  MACNAME -- return the name of a macro given its internal id
  547 **
  548 **  Parameter:
  549 **      n -- the id of the macro
  550 **
  551 **  Returns:
  552 **      The name of n.
  553 **
  554 **  Side Effects:
  555 **      none.
  556 **
  557 **  WARNING:
  558 **      Not thread-safe.
  559 */
  560 
  561 char *
  562 macname(n)
  563     int n;
  564 {
  565     static char mbuf[2];
  566 
  567     n = (int)(unsigned char)n;
  568     if (n > MAXMACROID)
  569         return "***OUT OF RANGE MACRO***";
  570 
  571     /* if not ASCII printable, look up the name */
  572     if (n <= 0x20 || n > 0x7f)
  573     {
  574         char *p = MacroName[n];
  575 
  576         if (p != NULL)
  577             return p;
  578         return "***UNDEFINED MACRO***";
  579     }
  580 
  581     /* if in the ASCII graphic range, just return the id directly */
  582     mbuf[0] = n;
  583     mbuf[1] = '\0';
  584     return mbuf;
  585 }
  586 
  587 /*
  588 **  MACID_PARSE -- return id of macro identified by its name
  589 **
  590 **  Parameters:
  591 **      p -- pointer to name string -- either a single
  592 **          character or {name}.
  593 **      ep -- filled in with the pointer to the byte
  594 **          after the name.
  595 **
  596 **  Returns:
  597 **      0 -- An error was detected.
  598 **      1..MAXMACROID -- The internal id code for this macro.
  599 **
  600 **  Side Effects:
  601 **      If this is a new macro name, a new id is allocated.
  602 **      On error, syserr is called.
  603 */
  604 
  605 int
  606 macid_parse(p, ep)
  607     char *p;
  608     char **ep;
  609 {
  610     int mid;
  611     char *bp;
  612     char mbuf[MAXMACNAMELEN + 1];
  613 
  614     if (tTd(35, 14))
  615     {
  616         sm_dprintf("macid(");
  617         xputs(sm_debug_file(), p);
  618         sm_dprintf(") => ");
  619     }
  620 
  621     if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
  622     {
  623         syserr("Name required for macro/class");
  624         if (ep != NULL)
  625             *ep = p;
  626         if (tTd(35, 14))
  627             sm_dprintf("NULL\n");
  628         return 0;
  629     }
  630     if (*p != '{')
  631     {
  632         /* the macro is its own code */
  633         if (ep != NULL)
  634             *ep = p + 1;
  635         if (tTd(35, 14))
  636         {
  637             char buf[2];
  638 
  639             buf[0] = *p;
  640             buf[1] = '\0';
  641             xputs(sm_debug_file(), buf);
  642             sm_dprintf("\n");
  643         }
  644         return bitidx(*p);
  645     }
  646     bp = mbuf;
  647     while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
  648     {
  649         if (isascii(*p) && (isalnum(*p) || *p == '_'))
  650             *bp++ = *p;
  651         else
  652             syserr("Invalid macro/class character %c", *p);
  653     }
  654     *bp = '\0';
  655     mid = -1;
  656     if (*p == '\0')
  657     {
  658         syserr("Unbalanced { on %s", mbuf); /* missing } */
  659     }
  660     else if (*p != '}')
  661     {
  662         syserr("Macro/class name ({%s}) too long (%d chars max)",
  663             mbuf, (int) (sizeof(mbuf) - 1));
  664     }
  665     else if (mbuf[1] == '\0' && mbuf[0] >= 0x20)
  666     {
  667         /* ${x} == $x */
  668         mid = bitidx(mbuf[0]);
  669         p++;
  670     }
  671     else
  672     {
  673         STAB *s;
  674 
  675         s = stab(mbuf, ST_MACRO, ST_ENTER);
  676         if (s->s_macro != 0)
  677             mid = s->s_macro;
  678         else
  679         {
  680             if (NextMacroId > MAXMACROID)
  681             {
  682                 syserr("Macro/class {%s}: too many long names",
  683                     mbuf);
  684                 s->s_macro = -1;
  685             }
  686             else
  687             {
  688                 MacroName[NextMacroId] = s->s_name;
  689                 s->s_macro = mid = NextMacroId;
  690                 NextMacroId = NEXTMACROID(NextMacroId);
  691             }
  692         }
  693         p++;
  694     }
  695     if (ep != NULL)
  696         *ep = p;
  697     if (mid < 0 || mid > MAXMACROID)
  698     {
  699         syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
  700         if (tTd(35, 14))
  701             sm_dprintf("NULL\n");
  702         return 0;
  703     }
  704     if (tTd(35, 14))
  705         sm_dprintf("0x%x\n", mid);
  706     return mid;
  707 }
  708 
  709 /*
  710 **  WORDINCLASS -- tell if a word is in a specific class
  711 **
  712 **  Parameters:
  713 **      str -- the name of the word to look up.
  714 **      cl -- the class name.
  715 **
  716 **  Returns:
  717 **      true if str can be found in cl.
  718 **      false otherwise.
  719 */
  720 
  721 bool
  722 wordinclass(str, cl)
  723     char *str;
  724     int cl;
  725 {
  726     STAB *s;
  727 
  728     s = stab(str, ST_CLASS, ST_FIND);
  729     return s != NULL && bitnset(bitidx(cl), s->s_class);
  730 }