diff options
Diffstat (limited to 'contrib/sendmail/src/macro.c')
-rw-r--r-- | contrib/sendmail/src/macro.c | 350 |
1 files changed, 238 insertions, 112 deletions
diff --git a/contrib/sendmail/src/macro.c b/contrib/sendmail/src/macro.c index 70e18e4..fc7a2c2 100644 --- a/contrib/sendmail/src/macro.c +++ b/contrib/sendmail/src/macro.c @@ -11,19 +11,89 @@ * */ -#ifndef lint -static char id[] = "@(#)$Id: macro.c,v 8.40.16.9 2001/02/22 01:16:55 gshapiro Exp $"; -#endif /* ! lint */ - #include <sendmail.h> +SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro Exp $") + #if MAXMACROID != (BITMAPBITS - 1) ERROR Read the comment in conf.h #endif /* MAXMACROID != (BITMAPBITS - 1) */ -char *MacroName[MAXMACROID + 1]; /* macro id to name table */ -int NextMacroId = 0240; /* codes for long named macros */ +static char *MacroName[MAXMACROID + 1]; /* macro id to name table */ +int NextMacroId = 0240; /* codes for long named macros */ + +/* +** INITMACROS -- initialize the macro system +** +** This just involves defining some macros that are actually +** used internally as metasymbols to be themselves. +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** initializes several macros to be themselves. +*/ + +struct metamac MetaMacros[] = +{ + /* LHS pattern matching characters */ + { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE }, + { '=', MATCHCLASS }, { '~', MATCHNCLASS }, + + /* these are RHS metasymbols */ + { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER }, + { '>', CALLSUBR }, + + /* the conditional operations */ + { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI }, + + /* the hostname lookup characters */ + { '[', HOSTBEGIN }, { ']', HOSTEND }, + { '(', LOOKUPBEGIN }, { ')', LOOKUPEND }, + + /* miscellaneous control characters */ + { '&', MACRODEXPAND }, + + { '\0', '\0' } +}; + +#define MACBINDING(name, mid) \ + stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \ + MacroName[mid] = name; +void +initmacros(e) + register ENVELOPE *e; +{ + register struct metamac *m; + register int c; + char buf[5]; + + for (m = MetaMacros; m->metaname != '\0'; m++) + { + buf[0] = m->metaval; + buf[1] = '\0'; + macdefine(&e->e_macro, A_TEMP, m->metaname, buf); + } + buf[0] = MATCHREPL; + buf[2] = '\0'; + for (c = '0'; c <= '9'; c++) + { + buf[1] = c; + macdefine(&e->e_macro, A_TEMP, c, buf); + } + + /* set defaults for some macros sendmail will use later */ + macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON"); + + /* set up external names for some internal macros */ + MACBINDING("opMode", MID_OPMODE); + /*XXX should probably add equivalents for all short macros here XXX*/ +} /* ** EXPAND -- macro expand a string using $x escapes. ** @@ -50,8 +120,8 @@ expand(s, buf, bufsize, e) register char *xp; register char *q; bool skipping; /* set if conditionally skipping output */ - bool recurse = FALSE; /* set if recursion required */ - int i; + bool recurse; /* set if recursion required */ + size_t i; int skiplev; /* skipping nesting level */ int iflev; /* if nesting level */ char xbuf[MACBUFSIZE]; @@ -59,12 +129,13 @@ expand(s, buf, bufsize, e) if (tTd(35, 24)) { - dprintf("expand("); + sm_dprintf("expand("); xputs(s); - dprintf(")\n"); + sm_dprintf(")\n"); } - skipping = FALSE; + recurse = false; + skipping = false; skiplev = 0; iflev = 0; if (s == NULL) @@ -98,17 +169,17 @@ expand(s, buf, bufsize, e) case CONDELSE: /* change state of skipping */ if (iflev == 0) - break; + break; /* XXX: error */ if (skiplev == 0) skipping = !skipping; continue; case CONDFI: /* stop skipping */ if (iflev == 0) - break; + break; /* XXX: error */ iflev--; if (skiplev == 0) - skipping = FALSE; + skipping = false; if (skipping) skiplev--; continue; @@ -142,7 +213,7 @@ expand(s, buf, bufsize, e) { /* check for any sendmail metacharacters */ if ((c & 0340) == 0200) - recurse = TRUE; + recurse = true; *xp++ = c; } } @@ -151,9 +222,9 @@ expand(s, buf, bufsize, e) if (tTd(35, 24)) { - dprintf("expand ==> "); + sm_dprintf("expand ==> "); xputs(xbuf); - dprintf("\n"); + sm_dprintf("\n"); } /* recurse as appropriate */ @@ -172,109 +243,155 @@ expand(s, buf, bufsize, e) /* copy results out */ i = xp - xbuf; - if ((size_t)i >= bufsize) + if (i >= bufsize) i = bufsize - 1; memmove(buf, xbuf, i); buf[i] = '\0'; } -/* -** DEFINE -- define a macro. + +/* +** MACDEFINE -- bind a macro name to a value ** -** this would be better done using a #define macro. +** Set a macro to a value, with fancy storage management. +** macdefine will make a copy of the value, if required, +** and will ensure that the storage for the previous value +** is not leaked. ** ** Parameters: -** n -- the macro name. -** v -- the macro value. -** e -- the envelope to store the definition in. -** -** Returns: -** none. -** -** Side Effects: -** e->e_macro[n] is defined. -** -** Notes: -** There is one macro for each ASCII character, -** although they are not all used. The currently -** defined macros are: -** -** $a date in ARPANET format (preferring the Date: line -** of the message) -** $b the current date (as opposed to the date as found -** the message) in ARPANET format -** $c hop count -** $d (current) date in UNIX (ctime) format -** $e the SMTP entry message+ -** $f raw from address -** $g translated from address -** $h to host -** $i queue id -** $j official SMTP hostname, used in messages+ -** $k UUCP node name -** $l UNIX-style from line+ -** $m The domain part of our full name. -** $n name of sendmail ("MAILER-DAEMON" on local -** net typically)+ -** $o delimiters ("operators") for address tokens+ -** (set via OperatorChars option in V6 or later -** sendmail.cf files) -** $p my process id in decimal -** $q the string that becomes an address -- this is -** normally used to combine $g & $x. -** $r protocol used to talk to sender -** $s sender's host name -** $t the current time in seconds since 1/1/1970 -** $u to user -** $v version number of sendmail -** $w our host name (if it can be determined) -** $x signature (full name) of from person -** $y the tty id of our terminal -** $z home directory of to person -** $_ RFC1413 authenticated sender address -** -** Macros marked with + must be defined in the -** configuration file and are used internally, but -** are not set. -** -** There are also some macros that can be used -** arbitrarily to make the configuration file -** cleaner. In general all upper-case letters -** are available. +** mac -- Macro table. +** vclass -- storage class of 'value', ignored if value==NULL. +** A_HEAP means that the value was allocated by +** malloc, and that macdefine owns the storage. +** A_TEMP means that value points to temporary storage, +** and thus macdefine needs to make a copy. +** A_PERM means that value points to storage that +** will remain allocated and unchanged for +** at least the lifetime of mac. Use A_PERM if: +** -- value == NULL, +** -- value points to a string literal, +** -- value was allocated from mac->mac_rpool +** or (in the case of an envelope macro) +** from e->e_rpool, +** -- in the case of an envelope macro, +** value is a string member of the envelope +** such as e->e_sender. +** id -- Macro id. This is a single character macro name +** such as 'g', or a value returned by macid(). +** value -- Macro value: either NULL, or a string. */ void -define(n, v, e) - int n; - char *v; - register ENVELOPE *e; +#if SM_HEAP_CHECK +macdefine_tagged(mac, vclass, id, value, file, line, grp) +#else /* SM_HEAP_CHECK */ +macdefine(mac, vclass, id, value) +#endif /* SM_HEAP_CHECK */ + MACROS_T *mac; + ARGCLASS_T vclass; + int id; + char *value; +#if SM_HEAP_CHECK + char *file; + int line; + int grp; +#endif /* SM_HEAP_CHECK */ { - int m; + char *newvalue; + + if (id < 0 || id > MAXMACROID) + return; - m = bitidx(n); if (tTd(35, 9)) { - dprintf("%sdefine(%s as ", - (e->e_macro[m] == NULL) ? "" - : "re", macname(n)); - xputs(v); - dprintf(")\n"); + sm_dprintf("%sdefine(%s as ", + mac->mac_table[id] == NULL ? "" : "re", macname(id)); + xputs(value); + sm_dprintf(")\n"); + } + + if (mac->mac_rpool == NULL) + { + char *freeit = NULL; + + if (mac->mac_table[id] != NULL && + bitnset(id, mac->mac_allocated)) + freeit = mac->mac_table[id]; + + if (value == NULL || vclass == A_HEAP) + { + sm_heap_checkptr_tagged(value, file, line); + newvalue = value; + clrbitn(id, mac->mac_allocated); + } + else + { + newvalue = sm_strdup_tagged_x(value, file, line, 0); + setbitn(id, mac->mac_allocated); + } + mac->mac_table[id] = newvalue; + if (freeit != NULL) + sm_free(freeit); + } + else + { + if (value == NULL || vclass == A_PERM) + newvalue = value; + else + newvalue = sm_rpool_strdup_x(mac->mac_rpool, value); + mac->mac_table[id] = newvalue; + if (vclass == A_HEAP) + sm_free(value); } - e->e_macro[m] = v; #if _FFR_RESET_MACRO_GLOBALS - switch (m) + switch (id) { case 'j': - MyHostName = v; + PSTRSET(MyHostName, value); break; } #endif /* _FFR_RESET_MACRO_GLOBALS */ } -/* + +/* +** MACSET -- set a named macro to a value (low level) +** +** No fancy storage management; the caller takes full responsibility. +** Often used with macget; see also macdefine. +** +** Parameters: +** mac -- Macro table. +** i -- Macro name, specified as an integer offset. +** value -- Macro value: either NULL, or a string. +*/ + +void +macset(mac, i, value) + MACROS_T *mac; + int i; + char *value; +{ + if (i < 0 || i > MAXMACROID) + return; + + if (tTd(35, 9)) + { + sm_dprintf("macset(%s as ", macname(i)); + xputs(value); + sm_dprintf(")\n"); + } + mac->mac_table[i] = value; +} + +/* ** MACVALUE -- return uninterpreted value of a macro. ** +** Does fancy path searching. +** The low level counterpart is macget. +** ** Parameters: ** n -- the name of the macro. +** e -- envelope in which to start looking for the macro. ** ** Returns: ** The value of n. @@ -289,9 +406,16 @@ macvalue(n, e) register ENVELOPE *e; { n = bitidx(n); + if (e != NULL && e->e_mci != NULL) + { + register char *p = e->e_mci->mci_macro.mac_table[n]; + + if (p != NULL) + return p; + } while (e != NULL) { - register char *p = e->e_macro[n]; + register char *p = e->e_macro.mac_table[n]; if (p != NULL) return p; @@ -299,9 +423,9 @@ macvalue(n, e) break; e = e->e_parent; } - return NULL; + return GlobalMacros.mac_table[n]; } -/* +/* ** MACNAME -- return the name of a macro given its internal id ** ** Parameter: @@ -333,8 +457,8 @@ macname(n) mbuf[1] = '\0'; return mbuf; } -/* -** MACID -- return id of macro identified by its name +/* +** MACID_PARSE -- return id of macro identified by its name ** ** Parameters: ** p -- pointer to name string -- either a single @@ -343,15 +467,16 @@ macname(n) ** after the name. ** ** Returns: -** The internal id code for this macro. This will -** fit into a single byte. +** 0 -- An error was detected. +** 1..255 -- The internal id code for this macro. ** ** Side Effects: ** If this is a new macro name, a new id is allocated. +** On error, syserr is called. */ int -macid(p, ep) +macid_parse(p, ep) register char *p; char **ep; { @@ -361,9 +486,9 @@ macid(p, ep) if (tTd(35, 14)) { - dprintf("macid("); + sm_dprintf("macid("); xputs(p); - dprintf(") => "); + sm_dprintf(") => "); } if (*p == '\0' || (p[0] == '{' && p[1] == '}')) @@ -372,7 +497,7 @@ macid(p, ep) if (ep != NULL) *ep = p; if (tTd(35, 14)) - dprintf("NULL\n"); + sm_dprintf("NULL\n"); return 0; } if (*p != '{') @@ -381,7 +506,7 @@ macid(p, ep) if (ep != NULL) *ep = p + 1; if (tTd(35, 14)) - dprintf("%c\n", bitidx(*p)); + sm_dprintf("%c\n", bitidx(*p)); return bitidx(*p); } bp = mbuf; @@ -401,7 +526,7 @@ macid(p, ep) else if (*p != '}') { syserr("Macro/class name ({%s}) too long (%d chars max)", - mbuf, sizeof mbuf - 1); + mbuf, (int) (sizeof mbuf - 1)); } else if (mbuf[1] == '\0') { @@ -420,7 +545,8 @@ macid(p, ep) { if (NextMacroId > MAXMACROID) { - syserr("Macro/class {%s}: too many long names", mbuf); + syserr("Macro/class {%s}: too many long names", + mbuf); s->s_macro = -1; } else @@ -437,14 +563,14 @@ macid(p, ep) { syserr("Unable to assign macro/class ID (mid = 0x%x)", mid); if (tTd(35, 14)) - dprintf("NULL\n"); + sm_dprintf("NULL\n"); return 0; } if (tTd(35, 14)) - dprintf("0x%x\n", mid); + sm_dprintf("0x%x\n", mid); return mid; } -/* +/* ** WORDINCLASS -- tell if a word is in a specific class ** ** Parameters: @@ -452,8 +578,8 @@ macid(p, ep) ** cl -- the class name. ** ** Returns: -** TRUE if str can be found in cl. -** FALSE otherwise. +** true if str can be found in cl. +** false otherwise. */ bool |