xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 68199)
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*68199Seric static char sccsid[] = "@(#)macro.c	8.6 (Berkeley) 01/24/95";
1133729Sbostic #endif /* not lint */
1222707Sdist 
136056Seric # include "sendmail.h"
143379Seric 
1567767Seric char	*MacroName[256];	/* macro id to name table */
1667767Seric int	NextMacroId = 0240;	/* codes for long named macros */
1767767Seric 
1867767Seric 
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 
3660494Seric void
376980Seric expand(s, buf, buflim, e)
386980Seric 	register char *s;
396980Seric 	register char *buf;
406980Seric 	char *buflim;
416980Seric 	register ENVELOPE *e;
426980Seric {
4317349Seric 	register char *xp;
446056Seric 	register char *q;
459382Seric 	bool skipping;		/* set if conditionally skipping output */
4617349Seric 	bool recurse = FALSE;	/* set if recursion required */
4717349Seric 	int i;
4857589Seric 	int iflev;		/* if nesting level */
496056Seric 	char xbuf[BUFSIZ];
503379Seric 
5124941Seric 	if (tTd(35, 24))
526056Seric 	{
536056Seric 		printf("expand(");
546056Seric 		xputs(s);
556056Seric 		printf(")\n");
566056Seric 	}
573379Seric 
583387Seric 	skipping = FALSE;
5957589Seric 	iflev = 0;
608064Seric 	if (s == NULL)
618064Seric 		s = "";
6217349Seric 	for (xp = xbuf; *s != '\0'; s++)
633379Seric 	{
6464087Seric 		int 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;
7358050Seric 		switch (c & 0377)
743387Seric 		{
756056Seric 		  case CONDIF:		/* see if var set */
7657977Seric 			c = *++s;
7757977Seric 			if (skipping)
7857977Seric 				iflev++;
7957977Seric 			else
8057589Seric 				skipping = macvalue(c, e) == NULL;
8157977Seric 			continue;
823387Seric 
836056Seric 		  case CONDELSE:	/* change state of skipping */
8457977Seric 			if (iflev == 0)
8557589Seric 				skipping = !skipping;
866056Seric 			continue;
873387Seric 
886056Seric 		  case CONDFI:		/* stop skipping */
8957977Seric 			if (iflev == 0)
9057589Seric 				skipping = FALSE;
9157977Seric 			if (skipping)
9257977Seric 				iflev--;
9357977Seric 			continue;
943387Seric 
9558050Seric 		  case MACROEXPAND:	/* macro interpolation */
9667767Seric 			c = *++s & 0377;
9766019Seric 			if (c != '\0')
9866019Seric 				q = macvalue(c, e);
9966019Seric 			else
10066019Seric 			{
10166019Seric 				s--;
10266019Seric 				q = NULL;
10366019Seric 			}
1049382Seric 			if (q == NULL)
1053387Seric 				continue;
1066056Seric 			break;
1073387Seric 		}
1083387Seric 
1093379Seric 		/*
1103379Seric 		**  Interpolate q or output one character
1113379Seric 		*/
1123379Seric 
11317349Seric 		if (skipping || xp >= &xbuf[sizeof xbuf])
1143387Seric 			continue;
11517349Seric 		if (q == NULL)
11617349Seric 			*xp++ = c;
11717349Seric 		else
1186056Seric 		{
11917349Seric 			/* copy to end of q or max space remaining in buf */
12017349Seric 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
1216056Seric 			{
12258050Seric 				/* check for any sendmail metacharacters */
12358050Seric 				if ((c & 0340) == 0200)
12417349Seric 					recurse = TRUE;
1256056Seric 				*xp++ = c;
1266056Seric 			}
1276056Seric 		}
1283379Seric 	}
1296056Seric 	*xp = '\0';
1303379Seric 
13124941Seric 	if (tTd(35, 24))
1326056Seric 	{
1338064Seric 		printf("expand ==> ");
1346056Seric 		xputs(xbuf);
1358064Seric 		printf("\n");
1366056Seric 	}
1373379Seric 
1386056Seric 	/* recurse as appropriate */
13917349Seric 	if (recurse)
1409382Seric 	{
1419382Seric 		expand(xbuf, buf, buflim, e);
1429382Seric 		return;
1439382Seric 	}
1446056Seric 
1456056Seric 	/* copy results out */
14617349Seric 	i = buflim - buf - 1;
14717349Seric 	if (i > xp - xbuf)
14817349Seric 		i = xp - xbuf;
14917349Seric 	bcopy(xbuf, buf, i);
15017349Seric 	buf[i] = '\0';
1513379Seric }
1523379Seric /*
1533379Seric **  DEFINE -- define a macro.
1543379Seric **
1553379Seric **	this would be better done using a #define macro.
1563379Seric **
1573379Seric **	Parameters:
1583379Seric **		n -- the macro name.
1593379Seric **		v -- the macro value.
1609382Seric **		e -- the envelope to store the definition in.
1613379Seric **
1623379Seric **	Returns:
1633379Seric **		none.
1643379Seric **
1653379Seric **	Side Effects:
1669382Seric **		e->e_macro[n] is defined.
1674092Seric **
1684092Seric **	Notes:
1694092Seric **		There is one macro for each ASCII character,
1704092Seric **		although they are not all used.  The currently
1714092Seric **		defined macros are:
1724092Seric **
1734202Seric **		$a   date in ARPANET format (preferring the Date: line
1744202Seric **		     of the message)
1754202Seric **		$b   the current date (as opposed to the date as found
1764202Seric **		     the message) in ARPANET format
1774092Seric **		$c   hop count
1784202Seric **		$d   (current) date in UNIX (ctime) format
17910710Seric **		$e   the SMTP entry message+
1804092Seric **		$f   raw from address
1814092Seric **		$g   translated from address
1824092Seric **		$h   to host
1837851Seric **		$i   queue id
1847851Seric **		$j   official SMTP hostname, used in messages+
18557630Seric **		$k   UUCP node name
1864092Seric **		$l   UNIX-style from line+
18758319Seric **		$m   The domain part of our full name.
1884092Seric **		$n   name of sendmail ("MAILER-DAEMON" on local
1894092Seric **		     net typically)+
1904092Seric **		$o   delimiters ("operators") for address tokens+
1914092Seric **		$p   my process id in decimal
1925919Seric **		$q   the string that becomes an address -- this is
1935919Seric **		     normally used to combine $g & $x.
1945187Seric **		$r   protocol used to talk to sender
1955187Seric **		$s   sender's host name
1964092Seric **		$t   the current time in seconds since 1/1/1970
1974092Seric **		$u   to user
1984092Seric **		$v   version number of sendmail
19910407Seric **		$w   our host name (if it can be determined)
2004092Seric **		$x   signature (full name) of from person
2014202Seric **		$y   the tty id of our terminal
2024092Seric **		$z   home directory of to person
20358951Seric **		$_   RFC1413 authenticated sender address
2044092Seric **
2054092Seric **		Macros marked with + must be defined in the
2064092Seric **		configuration file and are used internally, but
2074092Seric **		are not set.
2084092Seric **
2094092Seric **		There are also some macros that can be used
2104092Seric **		arbitrarily to make the configuration file
2114092Seric **		cleaner.  In general all upper-case letters
2124092Seric **		are available.
2133379Seric */
2143379Seric 
21560494Seric void
2169382Seric define(n, v, e)
21764087Seric 	int n;
2183379Seric 	char *v;
2199382Seric 	register ENVELOPE *e;
2203379Seric {
22124941Seric 	if (tTd(35, 9))
2226056Seric 	{
22367767Seric 		printf("define(%s as ", macname(n));
2246056Seric 		xputs(v);
2256056Seric 		printf(")\n");
2266056Seric 	}
22767767Seric 	e->e_macro[n & 0377] = v;
2283379Seric }
2294454Seric /*
2304454Seric **  MACVALUE -- return uninterpreted value of a macro.
2314454Seric **
2324454Seric **	Parameters:
2334454Seric **		n -- the name of the macro.
2344454Seric **
2354454Seric **	Returns:
2364454Seric **		The value of n.
2374454Seric **
2384454Seric **	Side Effects:
2394454Seric **		none.
2404454Seric */
2414454Seric 
2424454Seric char *
2438182Seric macvalue(n, e)
24464087Seric 	int n;
2458182Seric 	register ENVELOPE *e;
2464454Seric {
24767767Seric 	n &= 0377;
2488182Seric 	while (e != NULL)
2498182Seric 	{
2508182Seric 		register char *p = e->e_macro[n];
2518182Seric 
2528182Seric 		if (p != NULL)
2538182Seric 			return (p);
2548182Seric 		e = e->e_parent;
2558182Seric 	}
2568182Seric 	return (NULL);
2574454Seric }
25867767Seric /*
25967767Seric **  MACNAME -- return the name of a macro given its internal id
26067767Seric **
26167767Seric **	Parameter:
26267767Seric **		n -- the id of the macro
26367767Seric **
26467767Seric **	Returns:
26567767Seric **		The name of n.
26667767Seric **
26767767Seric **	Side Effects:
26867767Seric **		none.
26967767Seric */
27067767Seric 
27167767Seric char *
27267767Seric macname(n)
27367767Seric 	int n;
27467767Seric {
27567767Seric 	static char mbuf[2];
27667767Seric 
27767767Seric 	n &= 0377;
27867767Seric 	if (bitset(0200, n))
27967767Seric 	{
28067767Seric 		char *p = MacroName[n];
28167767Seric 
28267767Seric 		if (p != NULL)
28367767Seric 			return p;
28467767Seric 		return "***UNDEFINED MACRO***";
28567767Seric 	}
28667767Seric 	mbuf[0] = n;
28767767Seric 	mbuf[1] = '\0';
28867767Seric 	return mbuf;
28967767Seric }
29067767Seric /*
29167767Seric **  MACID -- return id of macro identified by its name
29267767Seric **
29367767Seric **	Parameters:
29467767Seric **		p -- pointer to name string -- either a single
29567767Seric **			character or {name}.
29667767Seric **		ep -- filled in with the pointer to the byte
29767767Seric **			after the name.
29867767Seric **
29967767Seric **	Returns:
30067767Seric **		The internal id code for this macro.  This will
30167767Seric **		fit into a single byte.
30267767Seric **
30367767Seric **	Side Effects:
30467767Seric **		If this is a new macro name, a new id is allocated.
30567767Seric */
30667767Seric 
30767767Seric int
30867767Seric macid(p, ep)
30967767Seric 	register char *p;
31067767Seric 	char **ep;
31167767Seric {
31267767Seric 	int mid;
31367767Seric 	register char *bp;
31467767Seric 	char mbuf[21];
31567767Seric 
31667767Seric 	if (tTd(35, 14))
31767767Seric 		printf("macid(%s) => ", p);
31867767Seric 
31967815Seric 	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
32067767Seric 	{
32167767Seric 		syserr("Name required for macro/class");
32267767Seric 		if (ep != NULL)
32367767Seric 			*ep = p;
32467767Seric 		if (tTd(35, 14))
32567767Seric 			printf("NULL\n");
32667767Seric 		return '\0';
32767767Seric 	}
32867767Seric 	if (*p != '{')
32967767Seric 	{
33067767Seric 		/* the macro is its own code */
33167767Seric 		if (ep != NULL)
33267767Seric 			*ep = p + 1;
33367767Seric 		if (tTd(35, 14))
33467767Seric 			printf("%c\n", *p);
33567767Seric 		return *p;
33667767Seric 	}
33767767Seric 	bp = mbuf;
33867767Seric 	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf])
33967815Seric 	{
34067815Seric 		if (isascii(*p) && (isalnum(*p) || *p == '_'))
34167815Seric 			*bp++ = *p;
34267815Seric 		else
34367815Seric 			syserr("Invalid macro/class character %c", *p);
34467815Seric 	}
34567767Seric 	*bp = '\0';
34667767Seric 	mid = -1;
34767767Seric 	if (*p == '\0')
34867767Seric 	{
34967767Seric 		syserr("Unbalanced { on %s", mbuf);	/* missing } */
35067767Seric 	}
35167767Seric 	else if (*p != '}')
35267767Seric 	{
35367767Seric 		syserr("Macro/class name ({%s}) too long (%d chars max)",
35467767Seric 			mbuf, sizeof mbuf - 1);
35567767Seric 	}
35667767Seric 	else if (mbuf[1] == '\0')
35767767Seric 	{
35867767Seric 		/* ${x} == $x */
35967767Seric 		mid = mbuf[0];
36067767Seric 		p++;
36167767Seric 	}
36267767Seric 	else
36367767Seric 	{
36467767Seric 		register STAB *s;
36567767Seric 
36667767Seric 		s = stab(mbuf, ST_MACRO, ST_ENTER);
36767767Seric 		if (s->s_macro != 0)
36867767Seric 			mid = s->s_macro;
36967767Seric 		else
37067767Seric 		{
37167767Seric 			if (NextMacroId > 0377)
37267767Seric 			{
37367767Seric 				syserr("Macro/class {%s}: too many long names", mbuf);
37467767Seric 				s->s_macro = -1;
37567767Seric 			}
37667767Seric 			else
37767767Seric 			{
37867767Seric 				MacroName[NextMacroId] = s->s_name;
37967767Seric 				s->s_macro = mid = NextMacroId++;
38067767Seric 			}
38167767Seric 		}
38267767Seric 		p++;
38367767Seric 	}
38467767Seric 	if (ep != NULL)
38567767Seric 		*ep = p;
38667767Seric 	if (tTd(35, 14))
38767767Seric 		printf("0x%x\n", mid);
38867767Seric 	return mid;
38967767Seric }
390*68199Seric /*
391*68199Seric **  WORDINCLASS -- tell if a word is in a specific class
392*68199Seric **
393*68199Seric **	Parameters:
394*68199Seric **		word -- the name of the word to look up.
395*68199Seric **		cl -- the class name.
396*68199Seric **
397*68199Seric **	Returns:
398*68199Seric **		TRUE if word can be found in cl.
399*68199Seric **		FALSE otherwise.
400*68199Seric */
401*68199Seric 
402*68199Seric bool
403*68199Seric wordinclass(word, cl)
404*68199Seric 	char *word;
405*68199Seric 	char cl;
406*68199Seric {
407*68199Seric 	register STAB *s;
408*68199Seric 
409*68199Seric 	s = stab(word, ST_CLASS, ST_FIND);
410*68199Seric 	return s != NULL && bitnset(cl, s->s_class);
411*68199Seric }
412