xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 42826)
122707Sdist /*
234921Sbostic  * Copyright (c) 1983 Eric P. Allman
333729Sbostic  * Copyright (c) 1988 Regents of the University of California.
433729Sbostic  * All rights reserved.
533729Sbostic  *
6*42826Sbostic  * %sccs.include.redist.c%
733729Sbostic  */
822707Sdist 
922707Sdist #ifndef lint
10*42826Sbostic static char sccsid[] = "@(#)macro.c	5.7 (Berkeley) 06/01/90";
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 
326980Seric expand(s, buf, buflim, e)
336980Seric 	register char *s;
346980Seric 	register char *buf;
356980Seric 	char *buflim;
366980Seric 	register ENVELOPE *e;
376980Seric {
3817349Seric 	register char *xp;
396056Seric 	register char *q;
409382Seric 	bool skipping;		/* set if conditionally skipping output */
4117349Seric 	bool recurse = FALSE;	/* set if recursion required */
4217349Seric 	int i;
436056Seric 	char xbuf[BUFSIZ];
448182Seric 	extern char *macvalue();
453379Seric 
4624941Seric 	if (tTd(35, 24))
476056Seric 	{
486056Seric 		printf("expand(");
496056Seric 		xputs(s);
506056Seric 		printf(")\n");
516056Seric 	}
523379Seric 
533387Seric 	skipping = FALSE;
548064Seric 	if (s == NULL)
558064Seric 		s = "";
5617349Seric 	for (xp = xbuf; *s != '\0'; s++)
573379Seric 	{
586056Seric 		char c;
594319Seric 
604319Seric 		/*
616056Seric 		**  Check for non-ordinary (special?) character.
624319Seric 		**	'q' will be the interpolated quantity.
634319Seric 		*/
644319Seric 
653379Seric 		q = NULL;
666056Seric 		c = *s;
676056Seric 		switch (c)
683387Seric 		{
696056Seric 		  case CONDIF:		/* see if var set */
703387Seric 			c = *++s;
718182Seric 			skipping = macvalue(c, e) == NULL;
726056Seric 			continue;
733387Seric 
746056Seric 		  case CONDELSE:	/* change state of skipping */
756056Seric 			skipping = !skipping;
766056Seric 			continue;
773387Seric 
786056Seric 		  case CONDFI:		/* stop skipping */
796056Seric 			skipping = FALSE;
806056Seric 			continue;
813387Seric 
8216146Seric 		  case '\001':		/* macro interpolation */
836056Seric 			c = *++s;
848182Seric 			q = macvalue(c & 0177, e);
859382Seric 			if (q == NULL)
863387Seric 				continue;
876056Seric 			break;
883387Seric 		}
893387Seric 
903379Seric 		/*
913379Seric 		**  Interpolate q or output one character
923379Seric 		*/
933379Seric 
9417349Seric 		if (skipping || xp >= &xbuf[sizeof xbuf])
953387Seric 			continue;
9617349Seric 		if (q == NULL)
9717349Seric 			*xp++ = c;
9817349Seric 		else
996056Seric 		{
10017349Seric 			/* copy to end of q or max space remaining in buf */
10117349Seric 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1026056Seric 			{
10317349Seric 				if (iscntrl(c) && !isspace(c))
10417349Seric 					recurse = TRUE;
1056056Seric 				*xp++ = c;
1066056Seric 			}
1076056Seric 		}
1083379Seric 	}
1096056Seric 	*xp = '\0';
1103379Seric 
11124941Seric 	if (tTd(35, 24))
1126056Seric 	{
1138064Seric 		printf("expand ==> ");
1146056Seric 		xputs(xbuf);
1158064Seric 		printf("\n");
1166056Seric 	}
1173379Seric 
1186056Seric 	/* recurse as appropriate */
11917349Seric 	if (recurse)
1209382Seric 	{
1219382Seric 		expand(xbuf, buf, buflim, e);
1229382Seric 		return;
1239382Seric 	}
1246056Seric 
1256056Seric 	/* copy results out */
12617349Seric 	i = buflim - buf - 1;
12717349Seric 	if (i > xp - xbuf)
12817349Seric 		i = xp - xbuf;
12917349Seric 	bcopy(xbuf, buf, i);
13017349Seric 	buf[i] = '\0';
1313379Seric }
1323379Seric /*
1333379Seric **  DEFINE -- define a macro.
1343379Seric **
1353379Seric **	this would be better done using a #define macro.
1363379Seric **
1373379Seric **	Parameters:
1383379Seric **		n -- the macro name.
1393379Seric **		v -- the macro value.
1409382Seric **		e -- the envelope to store the definition in.
1413379Seric **
1423379Seric **	Returns:
1433379Seric **		none.
1443379Seric **
1453379Seric **	Side Effects:
1469382Seric **		e->e_macro[n] is defined.
1474092Seric **
1484092Seric **	Notes:
1494092Seric **		There is one macro for each ASCII character,
1504092Seric **		although they are not all used.  The currently
1514092Seric **		defined macros are:
1524092Seric **
1534202Seric **		$a   date in ARPANET format (preferring the Date: line
1544202Seric **		     of the message)
1554202Seric **		$b   the current date (as opposed to the date as found
1564202Seric **		     the message) in ARPANET format
1574092Seric **		$c   hop count
1584202Seric **		$d   (current) date in UNIX (ctime) format
15910710Seric **		$e   the SMTP entry message+
1604092Seric **		$f   raw from address
1614092Seric **		$g   translated from address
1624092Seric **		$h   to host
1637851Seric **		$i   queue id
1647851Seric **		$j   official SMTP hostname, used in messages+
1654092Seric **		$l   UNIX-style from line+
1664092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1674092Seric **		     net typically)+
1684092Seric **		$o   delimiters ("operators") for address tokens+
1694092Seric **		$p   my process id in decimal
1705919Seric **		$q   the string that becomes an address -- this is
1715919Seric **		     normally used to combine $g & $x.
1725187Seric **		$r   protocol used to talk to sender
1735187Seric **		$s   sender's host name
1744092Seric **		$t   the current time in seconds since 1/1/1970
1754092Seric **		$u   to user
1764092Seric **		$v   version number of sendmail
17710407Seric **		$w   our host name (if it can be determined)
1784092Seric **		$x   signature (full name) of from person
1794202Seric **		$y   the tty id of our terminal
1804092Seric **		$z   home directory of to person
1814092Seric **
1824092Seric **		Macros marked with + must be defined in the
1834092Seric **		configuration file and are used internally, but
1844092Seric **		are not set.
1854092Seric **
1864092Seric **		There are also some macros that can be used
1874092Seric **		arbitrarily to make the configuration file
1884092Seric **		cleaner.  In general all upper-case letters
1894092Seric **		are available.
1903379Seric */
1913379Seric 
1929382Seric define(n, v, e)
1933379Seric 	char n;
1943379Seric 	char *v;
1959382Seric 	register ENVELOPE *e;
1963379Seric {
19724941Seric 	if (tTd(35, 9))
1986056Seric 	{
1996056Seric 		printf("define(%c as ", n);
2006056Seric 		xputs(v);
2016056Seric 		printf(")\n");
2026056Seric 	}
2039382Seric 	e->e_macro[n & 0177] = v;
2043379Seric }
2054454Seric /*
2064454Seric **  MACVALUE -- return uninterpreted value of a macro.
2074454Seric **
2084454Seric **	Parameters:
2094454Seric **		n -- the name of the macro.
2104454Seric **
2114454Seric **	Returns:
2124454Seric **		The value of n.
2134454Seric **
2144454Seric **	Side Effects:
2154454Seric **		none.
2164454Seric */
2174454Seric 
2184454Seric char *
2198182Seric macvalue(n, e)
2204454Seric 	char n;
2218182Seric 	register ENVELOPE *e;
2224454Seric {
2238182Seric 	n &= 0177;
2248182Seric 	while (e != NULL)
2258182Seric 	{
2268182Seric 		register char *p = e->e_macro[n];
2278182Seric 
2288182Seric 		if (p != NULL)
2298182Seric 			return (p);
2308182Seric 		e = e->e_parent;
2318182Seric 	}
2328182Seric 	return (NULL);
2334454Seric }
234