summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/macro.c')
-rw-r--r--contrib/sendmail/src/macro.c350
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
OpenPOWER on IntegriCloud