xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 22707)
1*22707Sdist /*
2*22707Sdist **  Sendmail
3*22707Sdist **  Copyright (c) 1983  Eric P. Allman
4*22707Sdist **  Berkeley, California
5*22707Sdist **
6*22707Sdist **  Copyright (c) 1983 Regents of the University of California.
7*22707Sdist **  All rights reserved.  The Berkeley software License Agreement
8*22707Sdist **  specifies the terms and conditions for redistribution.
9*22707Sdist */
10*22707Sdist 
11*22707Sdist #ifndef lint
12*22707Sdist static char	SccsId[] = "@(#)macro.c	5.1 (Berkeley) 06/07/85";
13*22707Sdist #endif not lint
14*22707Sdist 
156056Seric # include "sendmail.h"
163379Seric 
17*22707Sdist SCCSID(@(#)macro.c	5.1		06/07/85);
183379Seric 
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.
253379Seric **		buflim -- the buffer limit, i.e., the address
263379Seric **			of the last usable position in buf.
276980Seric **		e -- envelope in which to work.
283379Seric **
293379Seric **	Returns:
309382Seric **		none.
313379Seric **
323379Seric **	Side Effects:
333379Seric **		none.
343379Seric */
353379Seric 
366980Seric expand(s, buf, buflim, e)
376980Seric 	register char *s;
386980Seric 	register char *buf;
396980Seric 	char *buflim;
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;
476056Seric 	char xbuf[BUFSIZ];
488182Seric 	extern char *macvalue();
493379Seric 
503379Seric # ifdef DEBUG
517677Seric 	if (tTd(35, 4))
526056Seric 	{
536056Seric 		printf("expand(");
546056Seric 		xputs(s);
556056Seric 		printf(")\n");
566056Seric 	}
573379Seric # endif DEBUG
583379Seric 
593387Seric 	skipping = FALSE;
608064Seric 	if (s == NULL)
618064Seric 		s = "";
6217349Seric 	for (xp = xbuf; *s != '\0'; s++)
633379Seric 	{
646056Seric 		char c;
654319Seric 
664319Seric 		/*
676056Seric 		**  Check for non-ordinary (special?) character.
684319Seric 		**	'q' will be the interpolated quantity.
694319Seric 		*/
704319Seric 
713379Seric 		q = NULL;
726056Seric 		c = *s;
736056Seric 		switch (c)
743387Seric 		{
756056Seric 		  case CONDIF:		/* see if var set */
763387Seric 			c = *++s;
778182Seric 			skipping = macvalue(c, e) == NULL;
786056Seric 			continue;
793387Seric 
806056Seric 		  case CONDELSE:	/* change state of skipping */
816056Seric 			skipping = !skipping;
826056Seric 			continue;
833387Seric 
846056Seric 		  case CONDFI:		/* stop skipping */
856056Seric 			skipping = FALSE;
866056Seric 			continue;
873387Seric 
8816146Seric 		  case '\001':		/* macro interpolation */
896056Seric 			c = *++s;
908182Seric 			q = macvalue(c & 0177, e);
919382Seric 			if (q == NULL)
923387Seric 				continue;
936056Seric 			break;
943387Seric 		}
953387Seric 
963379Seric 		/*
973379Seric 		**  Interpolate q or output one character
983379Seric 		*/
993379Seric 
10017349Seric 		if (skipping || xp >= &xbuf[sizeof xbuf])
1013387Seric 			continue;
10217349Seric 		if (q == NULL)
10317349Seric 			*xp++ = c;
10417349Seric 		else
1056056Seric 		{
10617349Seric 			/* copy to end of q or max space remaining in buf */
10717349Seric 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1086056Seric 			{
10917349Seric 				if (iscntrl(c) && !isspace(c))
11017349Seric 					recurse = TRUE;
1116056Seric 				*xp++ = c;
1126056Seric 			}
1136056Seric 		}
1143379Seric 	}
1156056Seric 	*xp = '\0';
1163379Seric 
1173379Seric # ifdef DEBUG
1187677Seric 	if (tTd(35, 4))
1196056Seric 	{
1208064Seric 		printf("expand ==> ");
1216056Seric 		xputs(xbuf);
1228064Seric 		printf("\n");
1236056Seric 	}
1243379Seric # endif DEBUG
1253379Seric 
1266056Seric 	/* recurse as appropriate */
12717349Seric 	if (recurse)
1289382Seric 	{
1299382Seric 		expand(xbuf, buf, buflim, e);
1309382Seric 		return;
1319382Seric 	}
1326056Seric 
1336056Seric 	/* copy results out */
13417349Seric 	i = buflim - buf - 1;
13517349Seric 	if (i > xp - xbuf)
13617349Seric 		i = xp - xbuf;
13717349Seric 	bcopy(xbuf, buf, i);
13817349Seric 	buf[i] = '\0';
1393379Seric }
1403379Seric /*
1413379Seric **  DEFINE -- define a macro.
1423379Seric **
1433379Seric **	this would be better done using a #define macro.
1443379Seric **
1453379Seric **	Parameters:
1463379Seric **		n -- the macro name.
1473379Seric **		v -- the macro value.
1489382Seric **		e -- the envelope to store the definition in.
1493379Seric **
1503379Seric **	Returns:
1513379Seric **		none.
1523379Seric **
1533379Seric **	Side Effects:
1549382Seric **		e->e_macro[n] is defined.
1554092Seric **
1564092Seric **	Notes:
1574092Seric **		There is one macro for each ASCII character,
1584092Seric **		although they are not all used.  The currently
1594092Seric **		defined macros are:
1604092Seric **
1614202Seric **		$a   date in ARPANET format (preferring the Date: line
1624202Seric **		     of the message)
1634202Seric **		$b   the current date (as opposed to the date as found
1644202Seric **		     the message) in ARPANET format
1654092Seric **		$c   hop count
1664202Seric **		$d   (current) date in UNIX (ctime) format
16710710Seric **		$e   the SMTP entry message+
1684092Seric **		$f   raw from address
1694092Seric **		$g   translated from address
1704092Seric **		$h   to host
1717851Seric **		$i   queue id
1727851Seric **		$j   official SMTP hostname, used in messages+
1734092Seric **		$l   UNIX-style from line+
1744092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1754092Seric **		     net typically)+
1764092Seric **		$o   delimiters ("operators") for address tokens+
1774092Seric **		$p   my process id in decimal
1785919Seric **		$q   the string that becomes an address -- this is
1795919Seric **		     normally used to combine $g & $x.
1805187Seric **		$r   protocol used to talk to sender
1815187Seric **		$s   sender's host name
1824092Seric **		$t   the current time in seconds since 1/1/1970
1834092Seric **		$u   to user
1844092Seric **		$v   version number of sendmail
18510407Seric **		$w   our host name (if it can be determined)
1864092Seric **		$x   signature (full name) of from person
1874202Seric **		$y   the tty id of our terminal
1884092Seric **		$z   home directory of to person
1894092Seric **
1904092Seric **		Macros marked with + must be defined in the
1914092Seric **		configuration file and are used internally, but
1924092Seric **		are not set.
1934092Seric **
1944092Seric **		There are also some macros that can be used
1954092Seric **		arbitrarily to make the configuration file
1964092Seric **		cleaner.  In general all upper-case letters
1974092Seric **		are available.
1983379Seric */
1993379Seric 
2009382Seric define(n, v, e)
2013379Seric 	char n;
2023379Seric 	char *v;
2039382Seric 	register ENVELOPE *e;
2043379Seric {
2053379Seric # ifdef DEBUG
2067677Seric 	if (tTd(35, 3))
2076056Seric 	{
2086056Seric 		printf("define(%c as ", n);
2096056Seric 		xputs(v);
2106056Seric 		printf(")\n");
2116056Seric 	}
2123379Seric # endif DEBUG
2139382Seric 	e->e_macro[n & 0177] = v;
2143379Seric }
2154454Seric /*
2164454Seric **  MACVALUE -- return uninterpreted value of a macro.
2174454Seric **
2184454Seric **	Parameters:
2194454Seric **		n -- the name of the macro.
2204454Seric **
2214454Seric **	Returns:
2224454Seric **		The value of n.
2234454Seric **
2244454Seric **	Side Effects:
2254454Seric **		none.
2264454Seric */
2274454Seric 
2284454Seric char *
2298182Seric macvalue(n, e)
2304454Seric 	char n;
2318182Seric 	register ENVELOPE *e;
2324454Seric {
2338182Seric 	n &= 0177;
2348182Seric 	while (e != NULL)
2358182Seric 	{
2368182Seric 		register char *p = e->e_macro[n];
2378182Seric 
2388182Seric 		if (p != NULL)
2398182Seric 			return (p);
2408182Seric 		e = e->e_parent;
2418182Seric 	}
2428182Seric 	return (NULL);
2434454Seric }
244