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