xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 66019)
122707Sdist /*
234921Sbostic  * Copyright (c) 1983 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*66019Seric static char sccsid[] = "@(#)macro.c	8.3 (Berkeley) 02/07/94";
1133729Sbostic #endif /* not lint */
1222707Sdist 
136056Seric # include "sendmail.h"
143379Seric 
153379Seric /*
163379Seric **  EXPAND -- macro expand a string using $x escapes.
173379Seric **
183379Seric **	Parameters:
193379Seric **		s -- the string to expand.
203379Seric **		buf -- the place to put the expansion.
213379Seric **		buflim -- the buffer limit, i.e., the address
223379Seric **			of the last usable position in buf.
236980Seric **		e -- envelope in which to work.
243379Seric **
253379Seric **	Returns:
269382Seric **		none.
273379Seric **
283379Seric **	Side Effects:
293379Seric **		none.
303379Seric */
313379Seric 
3260494Seric void
336980Seric expand(s, buf, buflim, e)
346980Seric 	register char *s;
356980Seric 	register char *buf;
366980Seric 	char *buflim;
376980Seric 	register ENVELOPE *e;
386980Seric {
3917349Seric 	register char *xp;
406056Seric 	register char *q;
419382Seric 	bool skipping;		/* set if conditionally skipping output */
4217349Seric 	bool recurse = FALSE;	/* set if recursion required */
4317349Seric 	int i;
4457589Seric 	int iflev;		/* if nesting level */
456056Seric 	char xbuf[BUFSIZ];
463379Seric 
4724941Seric 	if (tTd(35, 24))
486056Seric 	{
496056Seric 		printf("expand(");
506056Seric 		xputs(s);
516056Seric 		printf(")\n");
526056Seric 	}
533379Seric 
543387Seric 	skipping = FALSE;
5557589Seric 	iflev = 0;
568064Seric 	if (s == NULL)
578064Seric 		s = "";
5817349Seric 	for (xp = xbuf; *s != '\0'; s++)
593379Seric 	{
6064087Seric 		int c;
614319Seric 
624319Seric 		/*
636056Seric 		**  Check for non-ordinary (special?) character.
644319Seric 		**	'q' will be the interpolated quantity.
654319Seric 		*/
664319Seric 
673379Seric 		q = NULL;
686056Seric 		c = *s;
6958050Seric 		switch (c & 0377)
703387Seric 		{
716056Seric 		  case CONDIF:		/* see if var set */
7257977Seric 			c = *++s;
7357977Seric 			if (skipping)
7457977Seric 				iflev++;
7557977Seric 			else
7657589Seric 				skipping = macvalue(c, e) == NULL;
7757977Seric 			continue;
783387Seric 
796056Seric 		  case CONDELSE:	/* change state of skipping */
8057977Seric 			if (iflev == 0)
8157589Seric 				skipping = !skipping;
826056Seric 			continue;
833387Seric 
846056Seric 		  case CONDFI:		/* stop skipping */
8557977Seric 			if (iflev == 0)
8657589Seric 				skipping = FALSE;
8757977Seric 			if (skipping)
8857977Seric 				iflev--;
8957977Seric 			continue;
903387Seric 
9158050Seric 		  case MACROEXPAND:	/* macro interpolation */
92*66019Seric 			c = *++s & 0177;
93*66019Seric 			if (c != '\0')
94*66019Seric 				q = macvalue(c, e);
95*66019Seric 			else
96*66019Seric 			{
97*66019Seric 				s--;
98*66019Seric 				q = NULL;
99*66019Seric 			}
1009382Seric 			if (q == NULL)
1013387Seric 				continue;
1026056Seric 			break;
1033387Seric 		}
1043387Seric 
1053379Seric 		/*
1063379Seric 		**  Interpolate q or output one character
1073379Seric 		*/
1083379Seric 
10917349Seric 		if (skipping || xp >= &xbuf[sizeof xbuf])
1103387Seric 			continue;
11117349Seric 		if (q == NULL)
11217349Seric 			*xp++ = c;
11317349Seric 		else
1146056Seric 		{
11517349Seric 			/* copy to end of q or max space remaining in buf */
11617349Seric 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1176056Seric 			{
11858050Seric 				/* check for any sendmail metacharacters */
11958050Seric 				if ((c & 0340) == 0200)
12017349Seric 					recurse = TRUE;
1216056Seric 				*xp++ = c;
1226056Seric 			}
1236056Seric 		}
1243379Seric 	}
1256056Seric 	*xp = '\0';
1263379Seric 
12724941Seric 	if (tTd(35, 24))
1286056Seric 	{
1298064Seric 		printf("expand ==> ");
1306056Seric 		xputs(xbuf);
1318064Seric 		printf("\n");
1326056Seric 	}
1333379Seric 
1346056Seric 	/* recurse as appropriate */
13517349Seric 	if (recurse)
1369382Seric 	{
1379382Seric 		expand(xbuf, buf, buflim, e);
1389382Seric 		return;
1399382Seric 	}
1406056Seric 
1416056Seric 	/* copy results out */
14217349Seric 	i = buflim - buf - 1;
14317349Seric 	if (i > xp - xbuf)
14417349Seric 		i = xp - xbuf;
14517349Seric 	bcopy(xbuf, buf, i);
14617349Seric 	buf[i] = '\0';
1473379Seric }
1483379Seric /*
1493379Seric **  DEFINE -- define a macro.
1503379Seric **
1513379Seric **	this would be better done using a #define macro.
1523379Seric **
1533379Seric **	Parameters:
1543379Seric **		n -- the macro name.
1553379Seric **		v -- the macro value.
1569382Seric **		e -- the envelope to store the definition in.
1573379Seric **
1583379Seric **	Returns:
1593379Seric **		none.
1603379Seric **
1613379Seric **	Side Effects:
1629382Seric **		e->e_macro[n] is defined.
1634092Seric **
1644092Seric **	Notes:
1654092Seric **		There is one macro for each ASCII character,
1664092Seric **		although they are not all used.  The currently
1674092Seric **		defined macros are:
1684092Seric **
1694202Seric **		$a   date in ARPANET format (preferring the Date: line
1704202Seric **		     of the message)
1714202Seric **		$b   the current date (as opposed to the date as found
1724202Seric **		     the message) in ARPANET format
1734092Seric **		$c   hop count
1744202Seric **		$d   (current) date in UNIX (ctime) format
17510710Seric **		$e   the SMTP entry message+
1764092Seric **		$f   raw from address
1774092Seric **		$g   translated from address
1784092Seric **		$h   to host
1797851Seric **		$i   queue id
1807851Seric **		$j   official SMTP hostname, used in messages+
18157630Seric **		$k   UUCP node name
1824092Seric **		$l   UNIX-style from line+
18358319Seric **		$m   The domain part of our full name.
1844092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1854092Seric **		     net typically)+
1864092Seric **		$o   delimiters ("operators") for address tokens+
1874092Seric **		$p   my process id in decimal
1885919Seric **		$q   the string that becomes an address -- this is
1895919Seric **		     normally used to combine $g & $x.
1905187Seric **		$r   protocol used to talk to sender
1915187Seric **		$s   sender's host name
1924092Seric **		$t   the current time in seconds since 1/1/1970
1934092Seric **		$u   to user
1944092Seric **		$v   version number of sendmail
19510407Seric **		$w   our host name (if it can be determined)
1964092Seric **		$x   signature (full name) of from person
1974202Seric **		$y   the tty id of our terminal
1984092Seric **		$z   home directory of to person
19958951Seric **		$_   RFC1413 authenticated sender address
2004092Seric **
2014092Seric **		Macros marked with + must be defined in the
2024092Seric **		configuration file and are used internally, but
2034092Seric **		are not set.
2044092Seric **
2054092Seric **		There are also some macros that can be used
2064092Seric **		arbitrarily to make the configuration file
2074092Seric **		cleaner.  In general all upper-case letters
2084092Seric **		are available.
2093379Seric */
2103379Seric 
21160494Seric void
2129382Seric define(n, v, e)
21364087Seric 	int n;
2143379Seric 	char *v;
2159382Seric 	register ENVELOPE *e;
2163379Seric {
21724941Seric 	if (tTd(35, 9))
2186056Seric 	{
2196056Seric 		printf("define(%c as ", n);
2206056Seric 		xputs(v);
2216056Seric 		printf(")\n");
2226056Seric 	}
2239382Seric 	e->e_macro[n & 0177] = v;
2243379Seric }
2254454Seric /*
2264454Seric **  MACVALUE -- return uninterpreted value of a macro.
2274454Seric **
2284454Seric **	Parameters:
2294454Seric **		n -- the name of the macro.
2304454Seric **
2314454Seric **	Returns:
2324454Seric **		The value of n.
2334454Seric **
2344454Seric **	Side Effects:
2354454Seric **		none.
2364454Seric */
2374454Seric 
2384454Seric char *
2398182Seric macvalue(n, e)
24064087Seric 	int n;
2418182Seric 	register ENVELOPE *e;
2424454Seric {
2438182Seric 	n &= 0177;
2448182Seric 	while (e != NULL)
2458182Seric 	{
2468182Seric 		register char *p = e->e_macro[n];
2478182Seric 
2488182Seric 		if (p != NULL)
2498182Seric 			return (p);
2508182Seric 		e = e->e_parent;
2518182Seric 	}
2528182Seric 	return (NULL);
2534454Seric }
254