macro.c revision 66494
1/*
2 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#ifndef lint
15static char id[] = "@(#)$Id: macro.c,v 8.40.16.2 2000/09/17 17:04:26 gshapiro Exp $";
16#endif /* ! lint */
17
18#include <sendmail.h>
19
20char	*MacroName[256];	/* macro id to name table */
21int	NextMacroId = 0240;	/* codes for long named macros */
22
23
24/*
25**  EXPAND -- macro expand a string using $x escapes.
26**
27**	Parameters:
28**		s -- the string to expand.
29**		buf -- the place to put the expansion.
30**		bufsize -- the size of the buffer.
31**		e -- envelope in which to work.
32**
33**	Returns:
34**		none.
35**
36**	Side Effects:
37**		none.
38*/
39
40void
41expand(s, buf, bufsize, e)
42	register char *s;
43	register char *buf;
44	size_t bufsize;
45	register ENVELOPE *e;
46{
47	register char *xp;
48	register char *q;
49	bool skipping;		/* set if conditionally skipping output */
50	bool recurse = FALSE;	/* set if recursion required */
51	int i;
52	int skiplev;		/* skipping nesting level */
53	int iflev;		/* if nesting level */
54	char xbuf[MACBUFSIZE];
55	static int explevel = 0;
56
57	if (tTd(35, 24))
58	{
59		dprintf("expand(");
60		xputs(s);
61		dprintf(")\n");
62	}
63
64	skipping = FALSE;
65	skiplev = 0;
66	iflev = 0;
67	if (s == NULL)
68		s = "";
69	for (xp = xbuf; *s != '\0'; s++)
70	{
71		int c;
72
73		/*
74		**  Check for non-ordinary (special?) character.
75		**	'q' will be the interpolated quantity.
76		*/
77
78		q = NULL;
79		c = *s;
80		switch (c & 0377)
81		{
82		  case CONDIF:		/* see if var set */
83			iflev++;
84			c = *++s;
85			if (skipping)
86				skiplev++;
87			else
88			{
89				char *mv;
90
91				mv = macvalue(c, e);
92				skipping = (mv == NULL || *mv == '\0');
93			}
94			continue;
95
96		  case CONDELSE:	/* change state of skipping */
97			if (iflev == 0)
98				break;
99			if (skiplev == 0)
100				skipping = !skipping;
101			continue;
102
103		  case CONDFI:		/* stop skipping */
104			if (iflev == 0)
105				break;
106			iflev--;
107			if (skiplev == 0)
108				skipping = FALSE;
109			if (skipping)
110				skiplev--;
111			continue;
112
113		  case MACROEXPAND:	/* macro interpolation */
114			c = *++s & 0377;
115			if (c != '\0')
116				q = macvalue(c, e);
117			else
118			{
119				s--;
120				q = NULL;
121			}
122			if (q == NULL)
123				continue;
124			break;
125		}
126
127		/*
128		**  Interpolate q or output one character
129		*/
130
131		if (skipping || xp >= &xbuf[sizeof xbuf - 1])
132			continue;
133		if (q == NULL)
134			*xp++ = c;
135		else
136		{
137			/* copy to end of q or max space remaining in buf */
138			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
139			{
140				/* check for any sendmail metacharacters */
141				if ((c & 0340) == 0200)
142					recurse = TRUE;
143				*xp++ = c;
144			}
145		}
146	}
147	*xp = '\0';
148
149	if (tTd(35, 24))
150	{
151		dprintf("expand ==> ");
152		xputs(xbuf);
153		dprintf("\n");
154	}
155
156	/* recurse as appropriate */
157	if (recurse)
158	{
159		if (explevel < MaxMacroRecursion)
160		{
161			explevel++;
162			expand(xbuf, buf, bufsize, e);
163			explevel--;
164			return;
165		}
166		syserr("expand: recursion too deep (%d max)",
167			MaxMacroRecursion);
168	}
169
170	/* copy results out */
171	i = xp - xbuf;
172	if ((size_t)i >= bufsize)
173		i = bufsize - 1;
174	memmove(buf, xbuf, i);
175	buf[i] = '\0';
176}
177/*
178**  DEFINE -- define a macro.
179**
180**	this would be better done using a #define macro.
181**
182**	Parameters:
183**		n -- the macro name.
184**		v -- the macro value.
185**		e -- the envelope to store the definition in.
186**
187**	Returns:
188**		none.
189**
190**	Side Effects:
191**		e->e_macro[n] is defined.
192**
193**	Notes:
194**		There is one macro for each ASCII character,
195**		although they are not all used.  The currently
196**		defined macros are:
197**
198**		$a   date in ARPANET format (preferring the Date: line
199**		     of the message)
200**		$b   the current date (as opposed to the date as found
201**		     the message) in ARPANET format
202**		$c   hop count
203**		$d   (current) date in UNIX (ctime) format
204**		$e   the SMTP entry message+
205**		$f   raw from address
206**		$g   translated from address
207**		$h   to host
208**		$i   queue id
209**		$j   official SMTP hostname, used in messages+
210**		$k   UUCP node name
211**		$l   UNIX-style from line+
212**		$m   The domain part of our full name.
213**		$n   name of sendmail ("MAILER-DAEMON" on local
214**		     net typically)+
215**		$o   delimiters ("operators") for address tokens+
216**		     (set via OperatorChars option in V6 or later
217**		      sendmail.cf files)
218**		$p   my process id in decimal
219**		$q   the string that becomes an address -- this is
220**		     normally used to combine $g & $x.
221**		$r   protocol used to talk to sender
222**		$s   sender's host name
223**		$t   the current time in seconds since 1/1/1970
224**		$u   to user
225**		$v   version number of sendmail
226**		$w   our host name (if it can be determined)
227**		$x   signature (full name) of from person
228**		$y   the tty id of our terminal
229**		$z   home directory of to person
230**		$_   RFC1413 authenticated sender address
231**
232**		Macros marked with + must be defined in the
233**		configuration file and are used internally, but
234**		are not set.
235**
236**		There are also some macros that can be used
237**		arbitrarily to make the configuration file
238**		cleaner.  In general all upper-case letters
239**		are available.
240*/
241
242void
243define(n, v, e)
244	int n;
245	char *v;
246	register ENVELOPE *e;
247{
248	int m;
249
250	m = n & 0377;
251	if (tTd(35, 9))
252	{
253		dprintf("%sdefine(%s as ",
254			(e->e_macro[m] == NULL) ? ""
255						: "re", macname(n));
256		xputs(v);
257		dprintf(")\n");
258	}
259	e->e_macro[m] = v;
260
261#if _FFR_RESET_MACRO_GLOBALS
262	switch (m)
263	{
264	  case 'j':
265		MyHostName = v;
266		break;
267	}
268#endif /* _FFR_RESET_MACRO_GLOBALS */
269}
270/*
271**  MACVALUE -- return uninterpreted value of a macro.
272**
273**	Parameters:
274**		n -- the name of the macro.
275**
276**	Returns:
277**		The value of n.
278**
279**	Side Effects:
280**		none.
281*/
282
283char *
284macvalue(n, e)
285	int n;
286	register ENVELOPE *e;
287{
288	n &= 0377;
289	while (e != NULL)
290	{
291		register char *p = e->e_macro[n];
292
293		if (p != NULL)
294			return p;
295		e = e->e_parent;
296	}
297	return NULL;
298}
299/*
300**  MACNAME -- return the name of a macro given its internal id
301**
302**	Parameter:
303**		n -- the id of the macro
304**
305**	Returns:
306**		The name of n.
307**
308**	Side Effects:
309**		none.
310*/
311
312char *
313macname(n)
314	int n;
315{
316	static char mbuf[2];
317
318	n &= 0377;
319	if (bitset(0200, n))
320	{
321		char *p = MacroName[n];
322
323		if (p != NULL)
324			return p;
325		return "***UNDEFINED MACRO***";
326	}
327	mbuf[0] = n;
328	mbuf[1] = '\0';
329	return mbuf;
330}
331/*
332**  MACID -- return id of macro identified by its name
333**
334**	Parameters:
335**		p -- pointer to name string -- either a single
336**			character or {name}.
337**		ep -- filled in with the pointer to the byte
338**			after the name.
339**
340**	Returns:
341**		The internal id code for this macro.  This will
342**		fit into a single byte.
343**
344**	Side Effects:
345**		If this is a new macro name, a new id is allocated.
346*/
347
348int
349macid(p, ep)
350	register char *p;
351	char **ep;
352{
353	int mid;
354	register char *bp;
355	char mbuf[MAXMACNAMELEN + 1];
356
357	if (tTd(35, 14))
358	{
359		dprintf("macid(");
360		xputs(p);
361		dprintf(") => ");
362	}
363
364	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
365	{
366		syserr("Name required for macro/class");
367		if (ep != NULL)
368			*ep = p;
369		if (tTd(35, 14))
370			dprintf("NULL\n");
371		return '\0';
372	}
373	if (*p != '{')
374	{
375		/* the macro is its own code */
376		if (ep != NULL)
377			*ep = p + 1;
378		if (tTd(35, 14))
379			dprintf("%c\n", *p);
380		return *p;
381	}
382	bp = mbuf;
383	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
384	{
385		if (isascii(*p) && (isalnum(*p) || *p == '_'))
386			*bp++ = *p;
387		else
388			syserr("Invalid macro/class character %c", *p);
389	}
390	*bp = '\0';
391	mid = -1;
392	if (*p == '\0')
393	{
394		syserr("Unbalanced { on %s", mbuf);	/* missing } */
395	}
396	else if (*p != '}')
397	{
398		syserr("Macro/class name ({%s}) too long (%d chars max)",
399			mbuf, sizeof mbuf - 1);
400	}
401	else if (mbuf[1] == '\0')
402	{
403		/* ${x} == $x */
404		mid = mbuf[0];
405		p++;
406	}
407	else
408	{
409		register STAB *s;
410
411		s = stab(mbuf, ST_MACRO, ST_ENTER);
412		if (s->s_macro != 0)
413			mid = s->s_macro;
414		else
415		{
416			if (NextMacroId > MAXMACROID)
417			{
418				syserr("Macro/class {%s}: too many long names", mbuf);
419				s->s_macro = -1;
420			}
421			else
422			{
423				MacroName[NextMacroId] = s->s_name;
424				s->s_macro = mid = NextMacroId++;
425			}
426		}
427		p++;
428	}
429	if (ep != NULL)
430		*ep = p;
431	if (tTd(35, 14))
432		dprintf("0x%x\n", mid);
433	return mid;
434}
435/*
436**  WORDINCLASS -- tell if a word is in a specific class
437**
438**	Parameters:
439**		str -- the name of the word to look up.
440**		cl -- the class name.
441**
442**	Returns:
443**		TRUE if str can be found in cl.
444**		FALSE otherwise.
445*/
446
447bool
448wordinclass(str, cl)
449	char *str;
450	int cl;
451{
452	register STAB *s;
453
454	s = stab(str, ST_CLASS, ST_FIND);
455	return s != NULL && bitnset(cl & 0xff, s->s_class);
456}
457