xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 69917)
122707Sdist /*
268839Seric  * Copyright (c) 1983, 1995 Eric P. Allman
362525Sbostic  * Copyright (c) 1988, 1993
462525Sbostic  *	The Regents of the University of California.  All rights reserved.
533729Sbostic  *
642826Sbostic  * %sccs.include.redist.c%
733729Sbostic  */
822707Sdist 
922707Sdist #ifndef lint
10*69917Seric static char sccsid[] = "@(#)macro.c	8.12 (Berkeley) 06/17/95";
1133729Sbostic #endif /* not lint */
1222707Sdist 
136056Seric # include "sendmail.h"
143379Seric 
1567767Seric char	*MacroName[256];	/* macro id to name table */
1667767Seric int	NextMacroId = 0240;	/* codes for long named macros */
1767767Seric 
1867767Seric 
193379Seric /*
203379Seric **  EXPAND -- macro expand a string using $x escapes.
213379Seric **
223379Seric **	Parameters:
233379Seric **		s -- the string to expand.
243379Seric **		buf -- the place to put the expansion.
2568529Seric **		bufsize -- the size of the buffer.
266980Seric **		e -- envelope in which to work.
273379Seric **
283379Seric **	Returns:
299382Seric **		none.
303379Seric **
313379Seric **	Side Effects:
323379Seric **		none.
333379Seric */
343379Seric 
3560494Seric void
expand(s,buf,bufsize,e)3668529Seric expand(s, buf, bufsize, e)
376980Seric 	register char *s;
386980Seric 	register char *buf;
3968529Seric 	size_t bufsize;
406980Seric 	register ENVELOPE *e;
416980Seric {
4217349Seric 	register char *xp;
436056Seric 	register char *q;
449382Seric 	bool skipping;		/* set if conditionally skipping output */
4517349Seric 	bool recurse = FALSE;	/* set if recursion required */
4617349Seric 	int i;
4757589Seric 	int iflev;		/* if nesting level */
486056Seric 	char xbuf[BUFSIZ];
493379Seric 
5024941Seric 	if (tTd(35, 24))
516056Seric 	{
526056Seric 		printf("expand(");
536056Seric 		xputs(s);
546056Seric 		printf(")\n");
556056Seric 	}
563379Seric 
573387Seric 	skipping = FALSE;
5857589Seric 	iflev = 0;
598064Seric 	if (s == NULL)
608064Seric 		s = "";
6117349Seric 	for (xp = xbuf; *s != '\0'; s++)
623379Seric 	{
6364087Seric 		int c;
644319Seric 
654319Seric 		/*
666056Seric 		**  Check for non-ordinary (special?) character.
674319Seric 		**	'q' will be the interpolated quantity.
684319Seric 		*/
694319Seric 
703379Seric 		q = NULL;
716056Seric 		c = *s;
7258050Seric 		switch (c & 0377)
733387Seric 		{
746056Seric 		  case CONDIF:		/* see if var set */
7557977Seric 			c = *++s;
7657977Seric 			if (skipping)
7757977Seric 				iflev++;
7857977Seric 			else
7957589Seric 				skipping = macvalue(c, e) == NULL;
8057977Seric 			continue;
813387Seric 
826056Seric 		  case CONDELSE:	/* change state of skipping */
8357977Seric 			if (iflev == 0)
8457589Seric 				skipping = !skipping;
856056Seric 			continue;
863387Seric 
876056Seric 		  case CONDFI:		/* stop skipping */
8857977Seric 			if (iflev == 0)
8957589Seric 				skipping = FALSE;
9057977Seric 			if (skipping)
9157977Seric 				iflev--;
9257977Seric 			continue;
933387Seric 
9458050Seric 		  case MACROEXPAND:	/* macro interpolation */
9567767Seric 			c = *++s & 0377;
9666019Seric 			if (c != '\0')
9766019Seric 				q = macvalue(c, e);
9866019Seric 			else
9966019Seric 			{
10066019Seric 				s--;
10166019Seric 				q = NULL;
10266019Seric 			}
1039382Seric 			if (q == NULL)
1043387Seric 				continue;
1056056Seric 			break;
1063387Seric 		}
1073387Seric 
1083379Seric 		/*
1093379Seric 		**  Interpolate q or output one character
1103379Seric 		*/
1113379Seric 
11217349Seric 		if (skipping || xp >= &xbuf[sizeof xbuf])
1133387Seric 			continue;
11417349Seric 		if (q == NULL)
11517349Seric 			*xp++ = c;
11617349Seric 		else
1176056Seric 		{
11817349Seric 			/* copy to end of q or max space remaining in buf */
11917349Seric 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1206056Seric 			{
12158050Seric 				/* check for any sendmail metacharacters */
12258050Seric 				if ((c & 0340) == 0200)
12317349Seric 					recurse = TRUE;
1246056Seric 				*xp++ = c;
1256056Seric 			}
1266056Seric 		}
1273379Seric 	}
1286056Seric 	*xp = '\0';
1293379Seric 
13024941Seric 	if (tTd(35, 24))
1316056Seric 	{
1328064Seric 		printf("expand ==> ");
1336056Seric 		xputs(xbuf);
1348064Seric 		printf("\n");
1356056Seric 	}
1363379Seric 
1376056Seric 	/* recurse as appropriate */
13817349Seric 	if (recurse)
1399382Seric 	{
14068529Seric 		expand(xbuf, buf, bufsize, e);
1419382Seric 		return;
1429382Seric 	}
1436056Seric 
1446056Seric 	/* copy results out */
14568529Seric 	i = xp - xbuf;
14668529Seric 	if (i >= bufsize)
14768529Seric 		i = bufsize - 1;
14817349Seric 	bcopy(xbuf, buf, i);
14917349Seric 	buf[i] = '\0';
1503379Seric }
1513379Seric /*
1523379Seric **  DEFINE -- define a macro.
1533379Seric **
1543379Seric **	this would be better done using a #define macro.
1553379Seric **
1563379Seric **	Parameters:
1573379Seric **		n -- the macro name.
1583379Seric **		v -- the macro value.
1599382Seric **		e -- the envelope to store the definition in.
1603379Seric **
1613379Seric **	Returns:
1623379Seric **		none.
1633379Seric **
1643379Seric **	Side Effects:
1659382Seric **		e->e_macro[n] is defined.
1664092Seric **
1674092Seric **	Notes:
1684092Seric **		There is one macro for each ASCII character,
1694092Seric **		although they are not all used.  The currently
1704092Seric **		defined macros are:
1714092Seric **
1724202Seric **		$a   date in ARPANET format (preferring the Date: line
1734202Seric **		     of the message)
1744202Seric **		$b   the current date (as opposed to the date as found
1754202Seric **		     the message) in ARPANET format
1764092Seric **		$c   hop count
1774202Seric **		$d   (current) date in UNIX (ctime) format
17810710Seric **		$e   the SMTP entry message+
1794092Seric **		$f   raw from address
1804092Seric **		$g   translated from address
1814092Seric **		$h   to host
1827851Seric **		$i   queue id
1837851Seric **		$j   official SMTP hostname, used in messages+
18457630Seric **		$k   UUCP node name
1854092Seric **		$l   UNIX-style from line+
18658319Seric **		$m   The domain part of our full name.
1874092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1884092Seric **		     net typically)+
1894092Seric **		$o   delimiters ("operators") for address tokens+
1904092Seric **		$p   my process id in decimal
1915919Seric **		$q   the string that becomes an address -- this is
1925919Seric **		     normally used to combine $g & $x.
1935187Seric **		$r   protocol used to talk to sender
1945187Seric **		$s   sender's host name
1954092Seric **		$t   the current time in seconds since 1/1/1970
1964092Seric **		$u   to user
1974092Seric **		$v   version number of sendmail
19810407Seric **		$w   our host name (if it can be determined)
1994092Seric **		$x   signature (full name) of from person
2004202Seric **		$y   the tty id of our terminal
2014092Seric **		$z   home directory of to person
20258951Seric **		$_   RFC1413 authenticated sender address
2034092Seric **
2044092Seric **		Macros marked with + must be defined in the
2054092Seric **		configuration file and are used internally, but
2064092Seric **		are not set.
2074092Seric **
2084092Seric **		There are also some macros that can be used
2094092Seric **		arbitrarily to make the configuration file
2104092Seric **		cleaner.  In general all upper-case letters
2114092Seric **		are available.
2123379Seric */
2133379Seric 
21460494Seric void
define(n,v,e)2159382Seric define(n, v, e)
21664087Seric 	int n;
2173379Seric 	char *v;
2189382Seric 	register ENVELOPE *e;
2193379Seric {
22024941Seric 	if (tTd(35, 9))
2216056Seric 	{
22267767Seric 		printf("define(%s as ", macname(n));
2236056Seric 		xputs(v);
2246056Seric 		printf(")\n");
2256056Seric 	}
22667767Seric 	e->e_macro[n & 0377] = v;
2273379Seric }
2284454Seric /*
2294454Seric **  MACVALUE -- return uninterpreted value of a macro.
2304454Seric **
2314454Seric **	Parameters:
2324454Seric **		n -- the name of the macro.
2334454Seric **
2344454Seric **	Returns:
2354454Seric **		The value of n.
2364454Seric **
2374454Seric **	Side Effects:
2384454Seric **		none.
2394454Seric */
2404454Seric 
2414454Seric char *
macvalue(n,e)2428182Seric macvalue(n, e)
24364087Seric 	int n;
2448182Seric 	register ENVELOPE *e;
2454454Seric {
24667767Seric 	n &= 0377;
2478182Seric 	while (e != NULL)
2488182Seric 	{
2498182Seric 		register char *p = e->e_macro[n];
2508182Seric 
2518182Seric 		if (p != NULL)
2528182Seric 			return (p);
2538182Seric 		e = e->e_parent;
2548182Seric 	}
2558182Seric 	return (NULL);
2564454Seric }
25767767Seric /*
25867767Seric **  MACNAME -- return the name of a macro given its internal id
25967767Seric **
26067767Seric **	Parameter:
26167767Seric **		n -- the id of the macro
26267767Seric **
26367767Seric **	Returns:
26467767Seric **		The name of n.
26567767Seric **
26667767Seric **	Side Effects:
26767767Seric **		none.
26867767Seric */
26967767Seric 
27067767Seric char *
macname(n)27167767Seric macname(n)
27267767Seric 	int n;
27367767Seric {
27467767Seric 	static char mbuf[2];
27567767Seric 
27667767Seric 	n &= 0377;
27767767Seric 	if (bitset(0200, n))
27867767Seric 	{
27967767Seric 		char *p = MacroName[n];
28067767Seric 
28167767Seric 		if (p != NULL)
28267767Seric 			return p;
28367767Seric 		return "***UNDEFINED MACRO***";
28467767Seric 	}
28567767Seric 	mbuf[0] = n;
28667767Seric 	mbuf[1] = '\0';
28767767Seric 	return mbuf;
28867767Seric }
28967767Seric /*
29067767Seric **  MACID -- return id of macro identified by its name
29167767Seric **
29267767Seric **	Parameters:
29367767Seric **		p -- pointer to name string -- either a single
29467767Seric **			character or {name}.
29567767Seric **		ep -- filled in with the pointer to the byte
29667767Seric **			after the name.
29767767Seric **
29867767Seric **	Returns:
29967767Seric **		The internal id code for this macro.  This will
30067767Seric **		fit into a single byte.
30167767Seric **
30267767Seric **	Side Effects:
30367767Seric **		If this is a new macro name, a new id is allocated.
30467767Seric */
30567767Seric 
30667767Seric int
macid(p,ep)30767767Seric macid(p, ep)
30867767Seric 	register char *p;
30967767Seric 	char **ep;
31067767Seric {
31167767Seric 	int mid;
31267767Seric 	register char *bp;
31367767Seric 	char mbuf[21];
31467767Seric 
31567767Seric 	if (tTd(35, 14))
316*69917Seric 	{
317*69917Seric 		printf("macid(");
318*69917Seric 		xputs(p);
319*69917Seric 		printf(") => ");
320*69917Seric 	}
32167767Seric 
32267815Seric 	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
32367767Seric 	{
32467767Seric 		syserr("Name required for macro/class");
32567767Seric 		if (ep != NULL)
32667767Seric 			*ep = p;
32767767Seric 		if (tTd(35, 14))
32867767Seric 			printf("NULL\n");
32967767Seric 		return '\0';
33067767Seric 	}
33167767Seric 	if (*p != '{')
33267767Seric 	{
33367767Seric 		/* the macro is its own code */
33467767Seric 		if (ep != NULL)
33567767Seric 			*ep = p + 1;
33667767Seric 		if (tTd(35, 14))
33767767Seric 			printf("%c\n", *p);
33867767Seric 		return *p;
33967767Seric 	}
34067767Seric 	bp = mbuf;
34167767Seric 	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf])
34267815Seric 	{
34367815Seric 		if (isascii(*p) && (isalnum(*p) || *p == '_'))
34467815Seric 			*bp++ = *p;
34567815Seric 		else
34667815Seric 			syserr("Invalid macro/class character %c", *p);
34767815Seric 	}
34867767Seric 	*bp = '\0';
34967767Seric 	mid = -1;
35067767Seric 	if (*p == '\0')
35167767Seric 	{
35267767Seric 		syserr("Unbalanced { on %s", mbuf);	/* missing } */
35367767Seric 	}
35467767Seric 	else if (*p != '}')
35567767Seric 	{
35667767Seric 		syserr("Macro/class name ({%s}) too long (%d chars max)",
35767767Seric 			mbuf, sizeof mbuf - 1);
35867767Seric 	}
35967767Seric 	else if (mbuf[1] == '\0')
36067767Seric 	{
36167767Seric 		/* ${x} == $x */
36267767Seric 		mid = mbuf[0];
36367767Seric 		p++;
36467767Seric 	}
36567767Seric 	else
36667767Seric 	{
36767767Seric 		register STAB *s;
36867767Seric 
36967767Seric 		s = stab(mbuf, ST_MACRO, ST_ENTER);
37067767Seric 		if (s->s_macro != 0)
37167767Seric 			mid = s->s_macro;
37267767Seric 		else
37367767Seric 		{
37467767Seric 			if (NextMacroId > 0377)
37567767Seric 			{
37667767Seric 				syserr("Macro/class {%s}: too many long names", mbuf);
37767767Seric 				s->s_macro = -1;
37867767Seric 			}
37967767Seric 			else
38067767Seric 			{
38167767Seric 				MacroName[NextMacroId] = s->s_name;
38267767Seric 				s->s_macro = mid = NextMacroId++;
38367767Seric 			}
38467767Seric 		}
38567767Seric 		p++;
38667767Seric 	}
38767767Seric 	if (ep != NULL)
38867767Seric 		*ep = p;
38967767Seric 	if (tTd(35, 14))
39067767Seric 		printf("0x%x\n", mid);
39167767Seric 	return mid;
39267767Seric }
39368199Seric /*
39468199Seric **  WORDINCLASS -- tell if a word is in a specific class
39568199Seric **
39668199Seric **	Parameters:
39768398Seric **		str -- the name of the word to look up.
39868199Seric **		cl -- the class name.
39968199Seric **
40068199Seric **	Returns:
40168398Seric **		TRUE if str can be found in cl.
40268199Seric **		FALSE otherwise.
40368199Seric */
40468199Seric 
40568199Seric bool
wordinclass(str,cl)40668398Seric wordinclass(str, cl)
40768398Seric 	char *str;
40868483Seric 	int cl;
40968199Seric {
41068199Seric 	register STAB *s;
41168199Seric 
41268398Seric 	s = stab(str, ST_CLASS, ST_FIND);
41368483Seric 	return s != NULL && bitnset(cl & 0xff, s->s_class);
41468199Seric }
415