macro.c revision 132943
1/*
2 * Copyright (c) 1998-2001, 2003 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#include <sendmail.h>
15
16SM_RCSID("@(#)$Id: macro.c,v 8.88 2003/09/05 23:11:18 ca Exp $")
17
18#if MAXMACROID != (BITMAPBITS - 1)
19	ERROR Read the comment in conf.h
20#endif /* MAXMACROID != (BITMAPBITS - 1) */
21
22static char	*MacroName[MAXMACROID + 1];	/* macro id to name table */
23int		NextMacroId = 0240;	/* codes for long named macros */
24
25/*
26**  INITMACROS -- initialize the macro system
27**
28**	This just involves defining some macros that are actually
29**	used internally as metasymbols to be themselves.
30**
31**	Parameters:
32**		none.
33**
34**	Returns:
35**		none.
36**
37**	Side Effects:
38**		initializes several macros to be themselves.
39*/
40
41struct metamac	MetaMacros[] =
42{
43	/* LHS pattern matching characters */
44	{ '*', MATCHZANY },	{ '+', MATCHANY },	{ '-', MATCHONE },
45	{ '=', MATCHCLASS },	{ '~', MATCHNCLASS },
46
47	/* these are RHS metasymbols */
48	{ '#', CANONNET },	{ '@', CANONHOST },	{ ':', CANONUSER },
49	{ '>', CALLSUBR },
50
51	/* the conditional operations */
52	{ '?', CONDIF },	{ '|', CONDELSE },	{ '.', CONDFI },
53
54	/* the hostname lookup characters */
55	{ '[', HOSTBEGIN },	{ ']', HOSTEND },
56	{ '(', LOOKUPBEGIN },	{ ')', LOOKUPEND },
57
58	/* miscellaneous control characters */
59	{ '&', MACRODEXPAND },
60
61	{ '\0', '\0' }
62};
63
64#define MACBINDING(name, mid) \
65		stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
66		MacroName[mid] = name;
67
68void
69initmacros(e)
70	register ENVELOPE *e;
71{
72	register struct metamac *m;
73	register int c;
74	char buf[5];
75
76	for (m = MetaMacros; m->metaname != '\0'; m++)
77	{
78		buf[0] = m->metaval;
79		buf[1] = '\0';
80		macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
81	}
82	buf[0] = MATCHREPL;
83	buf[2] = '\0';
84	for (c = '0'; c <= '9'; c++)
85	{
86		buf[1] = c;
87		macdefine(&e->e_macro, A_TEMP, c, buf);
88	}
89
90	/* set defaults for some macros sendmail will use later */
91	macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
92
93	/* set up external names for some internal macros */
94	MACBINDING("opMode", MID_OPMODE);
95	/*XXX should probably add equivalents for all short macros here XXX*/
96}
97/*
98**  EXPAND -- macro expand a string using $x escapes.
99**
100**	Parameters:
101**		s -- the string to expand.
102**		buf -- the place to put the expansion.
103**		bufsize -- the size of the buffer.
104**		e -- envelope in which to work.
105**
106**	Returns:
107**		none.
108**
109**	Side Effects:
110**		none.
111*/
112
113void
114expand(s, buf, bufsize, e)
115	register char *s;
116	register char *buf;
117	size_t bufsize;
118	register ENVELOPE *e;
119{
120	register char *xp;
121	register char *q;
122	bool skipping;		/* set if conditionally skipping output */
123	bool recurse;		/* set if recursion required */
124	size_t i;
125	int skiplev;		/* skipping nesting level */
126	int iflev;		/* if nesting level */
127	char xbuf[MACBUFSIZE];
128	static int explevel = 0;
129
130	if (tTd(35, 24))
131	{
132		sm_dprintf("expand(");
133		xputs(sm_debug_file(), s);
134		sm_dprintf(")\n");
135	}
136
137	recurse = false;
138	skipping = false;
139	skiplev = 0;
140	iflev = 0;
141	if (s == NULL)
142		s = "";
143	for (xp = xbuf; *s != '\0'; s++)
144	{
145		int c;
146
147		/*
148		**  Check for non-ordinary (special?) character.
149		**	'q' will be the interpolated quantity.
150		*/
151
152		q = NULL;
153		c = *s;
154		switch (c & 0377)
155		{
156		  case CONDIF:		/* see if var set */
157			iflev++;
158			c = *++s;
159			if (skipping)
160				skiplev++;
161			else
162			{
163				char *mv;
164
165				mv = macvalue(c, e);
166				skipping = (mv == NULL || *mv == '\0');
167			}
168			continue;
169
170		  case CONDELSE:	/* change state of skipping */
171			if (iflev == 0)
172				break;	/* XXX: error */
173			if (skiplev == 0)
174				skipping = !skipping;
175			continue;
176
177		  case CONDFI:		/* stop skipping */
178			if (iflev == 0)
179				break;	/* XXX: error */
180			iflev--;
181			if (skiplev == 0)
182				skipping = false;
183			if (skipping)
184				skiplev--;
185			continue;
186
187		  case MACROEXPAND:	/* macro interpolation */
188			c = bitidx(*++s);
189			if (c != '\0')
190				q = macvalue(c, e);
191			else
192			{
193				s--;
194				q = NULL;
195			}
196			if (q == NULL)
197				continue;
198			break;
199		}
200
201		/*
202		**  Interpolate q or output one character
203		*/
204
205		if (skipping || xp >= &xbuf[sizeof xbuf - 1])
206			continue;
207		if (q == NULL)
208			*xp++ = c;
209		else
210		{
211			/* copy to end of q or max space remaining in buf */
212			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
213			{
214				/* check for any sendmail metacharacters */
215				if ((c & 0340) == 0200)
216					recurse = true;
217				*xp++ = c;
218			}
219		}
220	}
221	*xp = '\0';
222
223	if (tTd(35, 24))
224	{
225		sm_dprintf("expand ==> ");
226		xputs(sm_debug_file(), xbuf);
227		sm_dprintf("\n");
228	}
229
230	/* recurse as appropriate */
231	if (recurse)
232	{
233		if (explevel < MaxMacroRecursion)
234		{
235			explevel++;
236			expand(xbuf, buf, bufsize, e);
237			explevel--;
238			return;
239		}
240		syserr("expand: recursion too deep (%d max)",
241			MaxMacroRecursion);
242	}
243
244	/* copy results out */
245	i = xp - xbuf;
246	if (i >= bufsize)
247		i = bufsize - 1;
248	memmove(buf, xbuf, i);
249	buf[i] = '\0';
250}
251
252/*
253**  MACDEFINE -- bind a macro name to a value
254**
255**	Set a macro to a value, with fancy storage management.
256**	macdefine will make a copy of the value, if required,
257**	and will ensure that the storage for the previous value
258**	is not leaked.
259**
260**	Parameters:
261**		mac -- Macro table.
262**		vclass -- storage class of 'value', ignored if value==NULL.
263**			A_HEAP	means that the value was allocated by
264**				malloc, and that macdefine owns the storage.
265**			A_TEMP	means that value points to temporary storage,
266**				and thus macdefine needs to make a copy.
267**			A_PERM	means that value points to storage that
268**				will remain allocated and unchanged for
269**				at least the lifetime of mac.  Use A_PERM if:
270**				-- value == NULL,
271**				-- value points to a string literal,
272**				-- value was allocated from mac->mac_rpool
273**				   or (in the case of an envelope macro)
274**				   from e->e_rpool,
275**				-- in the case of an envelope macro,
276**				   value is a string member of the envelope
277**				   such as e->e_sender.
278**		id -- Macro id.  This is a single character macro name
279**			such as 'g', or a value returned by macid().
280**		value -- Macro value: either NULL, or a string.
281*/
282
283void
284#if SM_HEAP_CHECK
285macdefine_tagged(mac, vclass, id, value, file, line, grp)
286#else /* SM_HEAP_CHECK */
287macdefine(mac, vclass, id, value)
288#endif /* SM_HEAP_CHECK */
289	MACROS_T *mac;
290	ARGCLASS_T vclass;
291	int id;
292	char *value;
293#if SM_HEAP_CHECK
294	char *file;
295	int line;
296	int grp;
297#endif /* SM_HEAP_CHECK */
298{
299	char *newvalue;
300
301	if (id < 0 || id > MAXMACROID)
302		return;
303
304	if (tTd(35, 9))
305	{
306		sm_dprintf("%sdefine(%s as ",
307			mac->mac_table[id] == NULL ? "" : "re", macname(id));
308		xputs(sm_debug_file(), value);
309		sm_dprintf(")\n");
310	}
311
312	if (mac->mac_rpool == NULL)
313	{
314		char *freeit = NULL;
315
316		if (mac->mac_table[id] != NULL &&
317		    bitnset(id, mac->mac_allocated))
318			freeit = mac->mac_table[id];
319
320		if (value == NULL || vclass == A_HEAP)
321		{
322			sm_heap_checkptr_tagged(value, file, line);
323			newvalue = value;
324			clrbitn(id, mac->mac_allocated);
325		}
326		else
327		{
328#if SM_HEAP_CHECK
329			newvalue = sm_strdup_tagged_x(value, file, line, 0);
330#else /* SM_HEAP_CHECK */
331			newvalue = sm_strdup_x(value);
332#endif /* SM_HEAP_CHECK */
333			setbitn(id, mac->mac_allocated);
334		}
335		mac->mac_table[id] = newvalue;
336		if (freeit != NULL)
337			sm_free(freeit);
338	}
339	else
340	{
341		if (value == NULL || vclass == A_PERM)
342			newvalue = value;
343		else
344			newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
345		mac->mac_table[id] = newvalue;
346		if (vclass == A_HEAP)
347			sm_free(value);
348	}
349
350#if _FFR_RESET_MACRO_GLOBALS
351	switch (id)
352	{
353	  case 'j':
354		PSTRSET(MyHostName, value);
355		break;
356	}
357#endif /* _FFR_RESET_MACRO_GLOBALS */
358}
359
360/*
361**  MACSET -- set a named macro to a value (low level)
362**
363**	No fancy storage management; the caller takes full responsibility.
364**	Often used with macget; see also macdefine.
365**
366**	Parameters:
367**		mac -- Macro table.
368**		i -- Macro name, specified as an integer offset.
369**		value -- Macro value: either NULL, or a string.
370*/
371
372void
373macset(mac, i, value)
374	MACROS_T *mac;
375	int i;
376	char *value;
377{
378	if (i < 0 || i > MAXMACROID)
379		return;
380
381	if (tTd(35, 9))
382	{
383		sm_dprintf("macset(%s as ", macname(i));
384		xputs(sm_debug_file(), value);
385		sm_dprintf(")\n");
386	}
387	mac->mac_table[i] = value;
388}
389
390/*
391**  MACVALUE -- return uninterpreted value of a macro.
392**
393**	Does fancy path searching.
394**	The low level counterpart is macget.
395**
396**	Parameters:
397**		n -- the name of the macro.
398**		e -- envelope in which to start looking for the macro.
399**
400**	Returns:
401**		The value of n.
402**
403**	Side Effects:
404**		none.
405*/
406
407char *
408macvalue(n, e)
409	int n;
410	register ENVELOPE *e;
411{
412	n = bitidx(n);
413	if (e != NULL && e->e_mci != NULL)
414	{
415		register char *p = e->e_mci->mci_macro.mac_table[n];
416
417		if (p != NULL)
418			return p;
419	}
420	while (e != NULL)
421	{
422		register char *p = e->e_macro.mac_table[n];
423
424		if (p != NULL)
425			return p;
426		if (e == e->e_parent)
427			break;
428		e = e->e_parent;
429	}
430	return GlobalMacros.mac_table[n];
431}
432/*
433**  MACNAME -- return the name of a macro given its internal id
434**
435**	Parameter:
436**		n -- the id of the macro
437**
438**	Returns:
439**		The name of n.
440**
441**	Side Effects:
442**		none.
443*/
444
445char *
446macname(n)
447	int n;
448{
449	static char mbuf[2];
450
451	n = bitidx(n);
452	if (bitset(0200, n))
453	{
454		char *p = MacroName[n];
455
456		if (p != NULL)
457			return p;
458		return "***UNDEFINED MACRO***";
459	}
460	mbuf[0] = n;
461	mbuf[1] = '\0';
462	return mbuf;
463}
464/*
465**  MACID_PARSE -- return id of macro identified by its name
466**
467**	Parameters:
468**		p -- pointer to name string -- either a single
469**			character or {name}.
470**		ep -- filled in with the pointer to the byte
471**			after the name.
472**
473**	Returns:
474**		0 -- An error was detected.
475**		1..255 -- The internal id code for this macro.
476**
477**	Side Effects:
478**		If this is a new macro name, a new id is allocated.
479**		On error, syserr is called.
480*/
481
482int
483macid_parse(p, ep)
484	register char *p;
485	char **ep;
486{
487	int mid;
488	register char *bp;
489	char mbuf[MAXMACNAMELEN + 1];
490
491	if (tTd(35, 14))
492	{
493		sm_dprintf("macid(");
494		xputs(sm_debug_file(), p);
495		sm_dprintf(") => ");
496	}
497
498	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
499	{
500		syserr("Name required for macro/class");
501		if (ep != NULL)
502			*ep = p;
503		if (tTd(35, 14))
504			sm_dprintf("NULL\n");
505		return 0;
506	}
507	if (*p != '{')
508	{
509		/* the macro is its own code */
510		if (ep != NULL)
511			*ep = p + 1;
512		if (tTd(35, 14))
513			sm_dprintf("%c\n", bitidx(*p));
514		return bitidx(*p);
515	}
516	bp = mbuf;
517	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
518	{
519		if (isascii(*p) && (isalnum(*p) || *p == '_'))
520			*bp++ = *p;
521		else
522			syserr("Invalid macro/class character %c", *p);
523	}
524	*bp = '\0';
525	mid = -1;
526	if (*p == '\0')
527	{
528		syserr("Unbalanced { on %s", mbuf);	/* missing } */
529	}
530	else if (*p != '}')
531	{
532		syserr("Macro/class name ({%s}) too long (%d chars max)",
533			mbuf, (int) (sizeof mbuf - 1));
534	}
535	else if (mbuf[1] == '\0')
536	{
537		/* ${x} == $x */
538		mid = bitidx(mbuf[0]);
539		p++;
540	}
541	else
542	{
543		register STAB *s;
544
545		s = stab(mbuf, ST_MACRO, ST_ENTER);
546		if (s->s_macro != 0)
547			mid = s->s_macro;
548		else
549		{
550			if (NextMacroId > MAXMACROID)
551			{
552				syserr("Macro/class {%s}: too many long names",
553					mbuf);
554				s->s_macro = -1;
555			}
556			else
557			{
558				MacroName[NextMacroId] = s->s_name;
559				s->s_macro = mid = NextMacroId++;
560			}
561		}
562		p++;
563	}
564	if (ep != NULL)
565		*ep = p;
566	if (mid < 0 || mid > MAXMACROID)
567	{
568		syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
569		if (tTd(35, 14))
570			sm_dprintf("NULL\n");
571		return 0;
572	}
573	if (tTd(35, 14))
574		sm_dprintf("0x%x\n", mid);
575	return mid;
576}
577/*
578**  WORDINCLASS -- tell if a word is in a specific class
579**
580**	Parameters:
581**		str -- the name of the word to look up.
582**		cl -- the class name.
583**
584**	Returns:
585**		true if str can be found in cl.
586**		false otherwise.
587*/
588
589bool
590wordinclass(str, cl)
591	char *str;
592	int cl;
593{
594	register STAB *s;
595
596	s = stab(str, ST_CLASS, ST_FIND);
597	return s != NULL && bitnset(bitidx(cl), s->s_class);
598}
599