xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 10407)
16056Seric # include "sendmail.h"
23379Seric 
3*10407Seric SCCSID(@(#)macro.c	3.19		01/17/83);
43379Seric 
53379Seric /*
63379Seric **  EXPAND -- macro expand a string using $x escapes.
73379Seric **
83379Seric **	Parameters:
93379Seric **		s -- the string to expand.
103379Seric **		buf -- the place to put the expansion.
113379Seric **		buflim -- the buffer limit, i.e., the address
123379Seric **			of the last usable position in buf.
136980Seric **		e -- envelope in which to work.
143379Seric **
153379Seric **	Returns:
169382Seric **		none.
173379Seric **
183379Seric **	Side Effects:
193379Seric **		none.
209382Seric **
219382Seric **	Bugs:
229382Seric **		The handling of $$ (to get one dollar) is rather bizarre,
239382Seric **			especially if there should be another macro
249382Seric **			expansion in the same string.
253379Seric */
263379Seric 
276980Seric expand(s, buf, buflim, e)
286980Seric 	register char *s;
296980Seric 	register char *buf;
306980Seric 	char *buflim;
316980Seric 	register ENVELOPE *e;
326980Seric {
336056Seric 	register char *q;
349382Seric 	bool skipping;		/* set if conditionally skipping output */
359382Seric 	bool gotone = FALSE;	/* set if any expansion done */
366056Seric 	char xbuf[BUFSIZ];
376056Seric 	register char *xp = xbuf;
388182Seric 	extern char *macvalue();
393379Seric 
403379Seric # ifdef DEBUG
417677Seric 	if (tTd(35, 4))
426056Seric 	{
436056Seric 		printf("expand(");
446056Seric 		xputs(s);
456056Seric 		printf(")\n");
466056Seric 	}
473379Seric # endif DEBUG
483379Seric 
493387Seric 	skipping = FALSE;
508064Seric 	if (s == NULL)
518064Seric 		s = "";
526056Seric 	for (; *s != '\0'; s++)
533379Seric 	{
546056Seric 		char c;
554319Seric 
564319Seric 		/*
576056Seric 		**  Check for non-ordinary (special?) character.
584319Seric 		**	'q' will be the interpolated quantity.
594319Seric 		*/
604319Seric 
613379Seric 		q = NULL;
626056Seric 		c = *s;
636056Seric 		switch (c)
643387Seric 		{
656056Seric 		  case CONDIF:		/* see if var set */
663387Seric 			c = *++s;
678182Seric 			skipping = macvalue(c, e) == NULL;
686056Seric 			continue;
693387Seric 
706056Seric 		  case CONDELSE:	/* change state of skipping */
716056Seric 			skipping = !skipping;
726056Seric 			continue;
733387Seric 
746056Seric 		  case CONDFI:		/* stop skipping */
756056Seric 			skipping = FALSE;
766056Seric 			continue;
773387Seric 
786056Seric 		  case '$':		/* macro interpolation */
796056Seric 			c = *++s;
809382Seric 			if (c == '$')
819382Seric 				break;
828182Seric 			q = macvalue(c & 0177, e);
839382Seric 			if (q == NULL)
843387Seric 				continue;
856056Seric 			gotone = TRUE;
866056Seric 			break;
873387Seric 		}
883387Seric 
893379Seric 		/*
903379Seric 		**  Interpolate q or output one character
913379Seric 		*/
923379Seric 
933387Seric 		if (skipping)
943387Seric 			continue;
956056Seric 		while (xp < &xbuf[sizeof xbuf])
966056Seric 		{
976056Seric 			if (q == NULL)
986056Seric 			{
996056Seric 				*xp++ = c;
1006056Seric 				break;
1016056Seric 			}
1029382Seric 			if (*q == '\0')
1036056Seric 				break;
1046056Seric 			*xp++ = *q++;
1056056Seric 		}
1063379Seric 	}
1076056Seric 	*xp = '\0';
1083379Seric 
1093379Seric # ifdef DEBUG
1107677Seric 	if (tTd(35, 4))
1116056Seric 	{
1128064Seric 		printf("expand ==> ");
1136056Seric 		xputs(xbuf);
1148064Seric 		printf("\n");
1156056Seric 	}
1163379Seric # endif DEBUG
1173379Seric 
1186056Seric 	/* recurse as appropriate */
1196056Seric 	if (gotone)
1209382Seric 	{
1219382Seric 		expand(xbuf, buf, buflim, e);
1229382Seric 		return;
1239382Seric 	}
1246056Seric 
1256056Seric 	/* copy results out */
1266056Seric 	for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
1276056Seric 		*q++ = *xp++;
1286056Seric 	*q = '\0';
1293379Seric }
1303379Seric /*
1313379Seric **  DEFINE -- define a macro.
1323379Seric **
1333379Seric **	this would be better done using a #define macro.
1343379Seric **
1353379Seric **	Parameters:
1363379Seric **		n -- the macro name.
1373379Seric **		v -- the macro value.
1389382Seric **		e -- the envelope to store the definition in.
1393379Seric **
1403379Seric **	Returns:
1413379Seric **		none.
1423379Seric **
1433379Seric **	Side Effects:
1449382Seric **		e->e_macro[n] is defined.
1454092Seric **
1464092Seric **	Notes:
1474092Seric **		There is one macro for each ASCII character,
1484092Seric **		although they are not all used.  The currently
1494092Seric **		defined macros are:
1504092Seric **
1514202Seric **		$a   date in ARPANET format (preferring the Date: line
1524202Seric **		     of the message)
1534202Seric **		$b   the current date (as opposed to the date as found
1544202Seric **		     the message) in ARPANET format
1554092Seric **		$c   hop count
1564202Seric **		$d   (current) date in UNIX (ctime) format
1574092Seric **		$f   raw from address
1584092Seric **		$g   translated from address
1594092Seric **		$h   to host
1607851Seric **		$i   queue id
1617851Seric **		$j   official SMTP hostname, used in messages+
1624092Seric **		$l   UNIX-style from line+
1634092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1644092Seric **		     net typically)+
1654092Seric **		$o   delimiters ("operators") for address tokens+
1664092Seric **		$p   my process id in decimal
1675919Seric **		$q   the string that becomes an address -- this is
1685919Seric **		     normally used to combine $g & $x.
1695187Seric **		$r   protocol used to talk to sender
1705187Seric **		$s   sender's host name
1714092Seric **		$t   the current time in seconds since 1/1/1970
1724092Seric **		$u   to user
1734092Seric **		$v   version number of sendmail
174*10407Seric **		$w   our host name (if it can be determined)
1754092Seric **		$x   signature (full name) of from person
1764202Seric **		$y   the tty id of our terminal
1774092Seric **		$z   home directory of to person
1784092Seric **
1794092Seric **		Macros marked with + must be defined in the
1804092Seric **		configuration file and are used internally, but
1814092Seric **		are not set.
1824092Seric **
1834092Seric **		There are also some macros that can be used
1844092Seric **		arbitrarily to make the configuration file
1854092Seric **		cleaner.  In general all upper-case letters
1864092Seric **		are available.
1873379Seric */
1883379Seric 
1899382Seric define(n, v, e)
1903379Seric 	char n;
1913379Seric 	char *v;
1929382Seric 	register ENVELOPE *e;
1933379Seric {
1943379Seric # ifdef DEBUG
1957677Seric 	if (tTd(35, 3))
1966056Seric 	{
1976056Seric 		printf("define(%c as ", n);
1986056Seric 		xputs(v);
1996056Seric 		printf(")\n");
2006056Seric 	}
2013379Seric # endif DEBUG
2029382Seric 	e->e_macro[n & 0177] = v;
2033379Seric }
2044454Seric /*
2054454Seric **  MACVALUE -- return uninterpreted value of a macro.
2064454Seric **
2074454Seric **	Parameters:
2084454Seric **		n -- the name of the macro.
2094454Seric **
2104454Seric **	Returns:
2114454Seric **		The value of n.
2124454Seric **
2134454Seric **	Side Effects:
2144454Seric **		none.
2154454Seric */
2164454Seric 
2174454Seric char *
2188182Seric macvalue(n, e)
2194454Seric 	char n;
2208182Seric 	register ENVELOPE *e;
2214454Seric {
2228182Seric 	n &= 0177;
2238182Seric 	while (e != NULL)
2248182Seric 	{
2258182Seric 		register char *p = e->e_macro[n];
2268182Seric 
2278182Seric 		if (p != NULL)
2288182Seric 			return (p);
2298182Seric 		e = e->e_parent;
2308182Seric 	}
2318182Seric 	return (NULL);
2324454Seric }
233