/*
* Copyright (c) 1998-2001, 2003, 2006, 2007 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sendmail.h>
#include <sm/sendmail.h>
#endif /* MAXMACROID != (BITMAPBITS - 1) */
/*
** Codes for long named macros.
** See also macname():
* if not ASCII printable, look up the name *
if (n <= 0x20 || n > 0x7f)
** First use 1 to NEXTMACROID_L, then use NEXTMACROID_H to MAXMACROID.
*/
#if _FFR_MORE_MACROS
/* table for next id in non-printable ASCII range: disallow some value */
static int NextMIdTable[] =
{
/* 0 nul */ 1,
/* 1 soh */ 2,
/* 2 stx */ 3,
/* 3 etx */ 4,
/* 4 eot */ 5,
/* 5 enq */ 6,
/* 6 ack */ 7,
/* 7 bel */ 8,
/* 8 bs */ 14,
/* 9 ht */ -1,
/* 10 nl */ -1,
/* 11 vt */ -1,
/* 12 np */ -1,
/* 13 cr */ -1,
/* 14 so */ 15,
/* 15 si */ 16,
/* 16 dle */ 17,
/* 17 dc1 */ 18,
/* 18 dc2 */ 19,
/* 19 dc3 */ 20,
/* 20 dc4 */ 21,
/* 21 nak */ 22,
/* 22 syn */ 23,
/* 23 etb */ 24,
/* 24 can */ 25,
/* 25 em */ 26,
/* 26 sub */ 27,
/* 27 esc */ 28,
/* 28 fs */ 29,
/* 29 gs */ 30,
/* 30 rs */ 31,
/* 31 us */ 32,
/* 32 sp */ -1,
};
/* see sendmail.h: Special characters in rewriting rules. */
#else /* _FFR_MORE_MACROS */
#endif /* _FFR_MORE_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.
*/
{
/* LHS pattern matching characters */
/* these are RHS metasymbols */
{ '>', CALLSUBR },
/* the conditional operations */
/* the hostname lookup characters */
/* miscellaneous control characters */
{ '&', MACRODEXPAND },
{ '\0', '\0' }
};
void
initmacros(e)
ENVELOPE *e;
{
struct metamac *m;
int c;
{
}
for (c = '0'; c <= '9'; c++)
{
buf[1] = c;
}
/* set defaults for some macros sendmail will use later */
/* set up external names for some internal macros */
/*XXX should probably add equivalents for all short macros here XXX*/
}
/*
**
** After expansion, the expansion will be in external form (that is,
** there will be no sendmail metacharacters and METAQUOTEs will have
** been stripped out).
**
** Parameters:
** s -- the string to expand.
** buf -- the place to put the expansion.
** bufsize -- the size of the buffer.
** explevel -- the depth of expansion (doexpand only)
** e -- envelope in which to work.
**
** Returns:
** none.
**
** Side Effects:
** none.
*/
static void
char *s;
char *buf;
int explevel;
ENVELOPE *e;
{
char *xp;
char *q;
size_t i;
{
sm_dprintf("expand(");
xputs(sm_debug_file(), s);
sm_dprintf(")\n");
}
recurse = false;
skipping = false;
skiplev = 0;
iflev = 0;
quotenext = false;
if (s == NULL)
s = "";
{
int c;
/*
** Check for non-ordinary (special?) character.
** 'q' will be the interpolated quantity.
*/
q = NULL;
c = *s & 0377;
if (quotenext)
{
quotenext = false;
goto simpleinterpolate;
}
switch (c)
{
case CONDIF: /* see if var set */
iflev++;
c = *++s & 0377;
if (skipping)
skiplev++;
else
{
char *mv;
}
continue;
case CONDELSE: /* change state of skipping */
if (iflev == 0)
break; /* XXX: error */
if (skiplev == 0)
continue;
case CONDFI: /* stop skipping */
if (iflev == 0)
break; /* XXX: error */
iflev--;
if (skiplev == 0)
skipping = false;
if (skipping)
skiplev--;
continue;
case MACROEXPAND: /* macro interpolation */
c = bitidx(*++s);
if (c != '\0')
q = macvalue(c, e);
else
{
s--;
q = NULL;
}
if (q == NULL)
continue;
break;
case METAQUOTE:
/* next octet completely quoted */
quotenext = true;
break;
}
/*
** Interpolate q or output one character
*/
continue;
if (q == NULL)
*xp++ = c;
else
{
/* copy to end of q or max space remaining in buf */
bool hiderecurse = false;
while ((c = *q++) != '\0' &&
{
/* check for any sendmail metacharacters */
recurse = true;
*xp++ = c;
/* give quoted characters a free ride */
}
}
}
*xp = '\0';
{
sm_dprintf("\n");
}
/* recurse as appropriate */
if (recurse)
{
if (explevel < MaxMacroRecursion)
{
return;
}
syserr("expand: recursion too deep (%d max)",
}
/* copy results out */
if (explevel == 0)
else
{
/* leave in internal form */
if (i >= bufsize)
i = bufsize - 1;
buf[i] = '\0';
}
{
sm_dprintf("expand ==> ");
sm_dprintf("\n");
}
}
void
char *s;
char *buf;
ENVELOPE *e;
{
}
/*
** MACDEFINE -- bind a macro name to a value
**
** 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:
** 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
#if SM_HEAP_CHECK
#else /* SM_HEAP_CHECK */
#endif /* SM_HEAP_CHECK */
int id;
char *value;
#if SM_HEAP_CHECK
char *file;
int line;
int grp;
#endif /* SM_HEAP_CHECK */
{
char *newvalue;
return;
{
sm_dprintf("%sdefine(%s as ",
sm_dprintf(")\n");
}
{
{
}
else
{
#if SM_HEAP_CHECK
#else /* SM_HEAP_CHECK */
#endif /* SM_HEAP_CHECK */
}
}
else
{
else
}
switch (id)
{
case 'j':
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
int i;
char *value;
{
if (i < 0 || i > MAXMACROID)
return;
{
sm_dprintf(")\n");
}
}
/*
** 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.
**
** Side Effects:
** none.
*/
char *
macvalue(n, e)
int n;
ENVELOPE *e;
{
n = bitidx(n);
{
if (p != NULL)
return p;
}
while (e != NULL)
{
if (p != NULL)
return p;
if (e == e->e_parent)
break;
e = e->e_parent;
}
return GlobalMacros.mac_table[n];
}
/*
** MACNAME -- return the name of a macro given its internal id
**
** Parameter:
** n -- the id of the macro
**
** Returns:
** The name of n.
**
** Side Effects:
** none.
**
** WARNING:
** Not thread-safe.
*/
char *
macname(n)
int n;
{
n = (int)(unsigned char)n;
if (n > MAXMACROID)
return "***OUT OF RANGE MACRO***";
/* if not ASCII printable, look up the name */
if (n <= 0x20 || n > 0x7f)
{
char *p = MacroName[n];
if (p != NULL)
return p;
return "***UNDEFINED MACRO***";
}
/* if in the ASCII graphic range, just return the id directly */
mbuf[0] = n;
return mbuf;
}
/*
** MACID_PARSE -- return id of macro identified by its name
**
** Parameters:
** p -- pointer to name string -- either a single
** character or {name}.
** ep -- filled in with the pointer to the byte
** after the name.
**
** Returns:
** 0 -- An error was detected.
** 1..MAXMACROID -- 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
char *p;
char **ep;
{
int mid;
char *bp;
{
sm_dprintf("macid(");
xputs(sm_debug_file(), p);
sm_dprintf(") => ");
}
if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
{
*ep = p;
sm_dprintf("NULL\n");
return 0;
}
if (*p != '{')
{
/* the macro is its own code */
*ep = p + 1;
{
buf[0] = *p;
sm_dprintf("\n");
}
return bitidx(*p);
}
{
*bp++ = *p;
else
}
*bp = '\0';
mid = -1;
if (*p == '\0')
{
}
else if (*p != '}')
{
}
{
/* ${x} == $x */
p++;
}
else
{
STAB *s;
if (s->s_macro != 0)
else
{
if (NextMacroId > MAXMACROID)
{
mbuf);
s->s_macro = -1;
}
else
{
}
}
p++;
}
*ep = p;
{
sm_dprintf("NULL\n");
return 0;
}
return mid;
}
/*
** WORDINCLASS -- tell if a word is in a specific class
**
** Parameters:
** str -- the name of the word to look up.
** cl -- the class name.
**
** Returns:
** true if str can be found in cl.
** false otherwise.
*/
bool
char *str;
int cl;
{
STAB *s;
}