16056Seric # include "sendmail.h"
23379Seric 
3*8182Seric SCCSID(@(#)macro.c	3.17		09/12/82);
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:
164319Seric **		End of interpolated output.
173379Seric **
183379Seric **	Side Effects:
193379Seric **		none.
203379Seric */
213379Seric 
226980Seric expand(s, buf, buflim, e)
236980Seric 	register char *s;
246980Seric 	register char *buf;
256980Seric 	char *buflim;
266980Seric 	register ENVELOPE *e;
276980Seric {
286980Seric 	extern char *expand2();
296980Seric 
306980Seric 	(void) expand2(s, buf, buflim, e);
316980Seric }
326980Seric 
336980Seric 
343379Seric char *
356980Seric expand2(s, buf, buflim, e)
363379Seric 	register char *s;
373379Seric 	register char *buf;
383379Seric 	char *buflim;
396980Seric 	register ENVELOPE *e;
403379Seric {
416056Seric 	register char *q;
426056Seric 	char xbuf[BUFSIZ];
436056Seric 	register char *xp = xbuf;
444319Seric 	bool skipping;		/* set if conditionally skipping output */
456056Seric 	bool gotone = FALSE;	/* set if any expansion done */
46*8182Seric 	extern char *macvalue();
473379Seric 
483379Seric # ifdef DEBUG
497677Seric 	if (tTd(35, 4))
506056Seric 	{
516056Seric 		printf("expand(");
526056Seric 		xputs(s);
536056Seric 		printf(")\n");
546056Seric 	}
553379Seric # endif DEBUG
563379Seric 
573387Seric 	skipping = FALSE;
588064Seric 	if (s == NULL)
598064Seric 		s = "";
606056Seric 	for (; *s != '\0'; s++)
613379Seric 	{
626056Seric 		char c;
634319Seric 
644319Seric 		/*
656056Seric 		**  Check for non-ordinary (special?) character.
664319Seric 		**	'q' will be the interpolated quantity.
674319Seric 		*/
684319Seric 
693379Seric 		q = NULL;
706056Seric 		c = *s;
716056Seric 		switch (c)
723387Seric 		{
736056Seric 		  case CONDIF:		/* see if var set */
743387Seric 			c = *++s;
75*8182Seric 			skipping = macvalue(c, e) == NULL;
766056Seric 			continue;
773387Seric 
786056Seric 		  case CONDELSE:	/* change state of skipping */
796056Seric 			skipping = !skipping;
806056Seric 			continue;
813387Seric 
826056Seric 		  case CONDFI:		/* stop skipping */
836056Seric 			skipping = FALSE;
846056Seric 			continue;
853387Seric 
866056Seric 		  case '$':		/* macro interpolation */
876056Seric 			c = *++s;
88*8182Seric 			q = macvalue(c & 0177, e);
894172Seric 			if (q == NULL && c != '$')
903387Seric 				continue;
916056Seric 			gotone = TRUE;
926056Seric 			break;
933387Seric 		}
943387Seric 
953379Seric 		/*
963379Seric 		**  Interpolate q or output one character
973379Seric 		*/
983379Seric 
993387Seric 		if (skipping)
1003387Seric 			continue;
1016056Seric 		while (xp < &xbuf[sizeof xbuf])
1026056Seric 		{
1036056Seric 			if (q == NULL)
1046056Seric 			{
1056056Seric 				*xp++ = c;
1066056Seric 				break;
1076056Seric 			}
1086056Seric 			if (*q == NULL)
1096056Seric 				break;
1106056Seric 			*xp++ = *q++;
1116056Seric 		}
1123379Seric 	}
1136056Seric 	*xp = '\0';
1143379Seric 
1153379Seric # ifdef DEBUG
1167677Seric 	if (tTd(35, 4))
1176056Seric 	{
1188064Seric 		printf("expand ==> ");
1196056Seric 		xputs(xbuf);
1208064Seric 		printf("\n");
1216056Seric 	}
1223379Seric # endif DEBUG
1233379Seric 
1246056Seric 	/* recurse as appropriate */
1256056Seric 	if (gotone)
1266980Seric 		return (expand2(xbuf, buf, buflim, e));
1276056Seric 
1286056Seric 	/* copy results out */
1296056Seric 	for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
1306056Seric 		*q++ = *xp++;
1316056Seric 	*q = '\0';
1326056Seric 
1336056Seric 	return (q);
1343379Seric }
1353379Seric /*
1363379Seric **  DEFINE -- define a macro.
1373379Seric **
1383379Seric **	this would be better done using a #define macro.
1393379Seric **
1403379Seric **	Parameters:
1413379Seric **		n -- the macro name.
1423379Seric **		v -- the macro value.
1433379Seric **
1443379Seric **	Returns:
1453379Seric **		none.
1463379Seric **
1473379Seric **	Side Effects:
1486980Seric **		CurEnv->e_macro[n] is defined.
1494092Seric **
1504092Seric **	Notes:
1514092Seric **		There is one macro for each ASCII character,
1524092Seric **		although they are not all used.  The currently
1534092Seric **		defined macros are:
1544092Seric **
1554202Seric **		$a   date in ARPANET format (preferring the Date: line
1564202Seric **		     of the message)
1574202Seric **		$b   the current date (as opposed to the date as found
1584202Seric **		     the message) in ARPANET format
1594092Seric **		$c   hop count
1604202Seric **		$d   (current) date in UNIX (ctime) format
1614092Seric **		$f   raw from address
1624092Seric **		$g   translated from address
1634092Seric **		$h   to host
1647851Seric **		$i   queue id
1657851Seric **		$j   official SMTP hostname, used in messages+
1664092Seric **		$l   UNIX-style from line+
1674092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1684092Seric **		     net typically)+
1694092Seric **		$o   delimiters ("operators") for address tokens+
1704092Seric **		$p   my process id in decimal
1715919Seric **		$q   the string that becomes an address -- this is
1725919Seric **		     normally used to combine $g & $x.
1735187Seric **		$r   protocol used to talk to sender
1745187Seric **		$s   sender's host name
1754092Seric **		$t   the current time in seconds since 1/1/1970
1764092Seric **		$u   to user
1774092Seric **		$v   version number of sendmail
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 
1923379Seric define(n, v)
1933379Seric 	char n;
1943379Seric 	char *v;
1953379Seric {
1963379Seric # ifdef DEBUG
1977677Seric 	if (tTd(35, 3))
1986056Seric 	{
1996056Seric 		printf("define(%c as ", n);
2006056Seric 		xputs(v);
2016056Seric 		printf(")\n");
2026056Seric 	}
2033379Seric # endif DEBUG
2046980Seric 	CurEnv->e_macro[n & 0177] = v;
2053379Seric }
2064454Seric /*
2074454Seric **  MACVALUE -- return uninterpreted value of a macro.
2084454Seric **
2094454Seric **	Parameters:
2104454Seric **		n -- the name of the macro.
2114454Seric **
2124454Seric **	Returns:
2134454Seric **		The value of n.
2144454Seric **
2154454Seric **	Side Effects:
2164454Seric **		none.
2174454Seric */
2184454Seric 
2194454Seric char *
220*8182Seric macvalue(n, e)
2214454Seric 	char n;
222*8182Seric 	register ENVELOPE *e;
2234454Seric {
224*8182Seric 	n &= 0177;
225*8182Seric 	while (e != NULL)
226*8182Seric 	{
227*8182Seric 		register char *p = e->e_macro[n];
228*8182Seric 
229*8182Seric 		if (p != NULL)
230*8182Seric 			return (p);
231*8182Seric 		e = e->e_parent;
232*8182Seric 	}
233*8182Seric 	return (NULL);
2344454Seric }
235