macro.c revision 95154
1/*
2 * Copyright (c) 1998-2001 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 1.1.1.7 2002/02/17 21:56:39 gshapiro 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(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(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(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			newvalue = sm_strdup_tagged_x(value, file, line, 0);
329			setbitn(id, mac->mac_allocated);
330		}
331		mac->mac_table[id] = newvalue;
332		if (freeit != NULL)
333			sm_free(freeit);
334	}
335	else
336	{
337		if (value == NULL || vclass == A_PERM)
338			newvalue = value;
339		else
340			newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
341		mac->mac_table[id] = newvalue;
342		if (vclass == A_HEAP)
343			sm_free(value);
344	}
345
346#if _FFR_RESET_MACRO_GLOBALS
347	switch (id)
348	{
349	  case 'j':
350		PSTRSET(MyHostName, value);
351		break;
352	}
353#endif /* _FFR_RESET_MACRO_GLOBALS */
354}
355
356/*
357**  MACSET -- set a named macro to a value (low level)
358**
359**	No fancy storage management; the caller takes full responsibility.
360**	Often used with macget; see also macdefine.
361**
362**	Parameters:
363**		mac -- Macro table.
364**		i -- Macro name, specified as an integer offset.
365**		value -- Macro value: either NULL, or a string.
366*/
367
368void
369macset(mac, i, value)
370	MACROS_T *mac;
371	int i;
372	char *value;
373{
374	if (i < 0 || i > MAXMACROID)
375		return;
376
377	if (tTd(35, 9))
378	{
379		sm_dprintf("macset(%s as ", macname(i));
380		xputs(value);
381		sm_dprintf(")\n");
382	}
383	mac->mac_table[i] = value;
384}
385
386/*
387**  MACVALUE -- return uninterpreted value of a macro.
388**
389**	Does fancy path searching.
390**	The low level counterpart is macget.
391**
392**	Parameters:
393**		n -- the name of the macro.
394**		e -- envelope in which to start looking for the macro.
395**
396**	Returns:
397**		The value of n.
398**
399**	Side Effects:
400**		none.
401*/
402
403char *
404macvalue(n, e)
405	int n;
406	register ENVELOPE *e;
407{
408	n = bitidx(n);
409	if (e != NULL && e->e_mci != NULL)
410	{
411		register char *p = e->e_mci->mci_macro.mac_table[n];
412
413		if (p != NULL)
414			return p;
415	}
416	while (e != NULL)
417	{
418		register char *p = e->e_macro.mac_table[n];
419
420		if (p != NULL)
421			return p;
422		if (e == e->e_parent)
423			break;
424		e = e->e_parent;
425	}
426	return GlobalMacros.mac_table[n];
427}
428/*
429**  MACNAME -- return the name of a macro given its internal id
430**
431**	Parameter:
432**		n -- the id of the macro
433**
434**	Returns:
435**		The name of n.
436**
437**	Side Effects:
438**		none.
439*/
440
441char *
442macname(n)
443	int n;
444{
445	static char mbuf[2];
446
447	n = bitidx(n);
448	if (bitset(0200, n))
449	{
450		char *p = MacroName[n];
451
452		if (p != NULL)
453			return p;
454		return "***UNDEFINED MACRO***";
455	}
456	mbuf[0] = n;
457	mbuf[1] = '\0';
458	return mbuf;
459}
460/*
461**  MACID_PARSE -- return id of macro identified by its name
462**
463**	Parameters:
464**		p -- pointer to name string -- either a single
465**			character or {name}.
466**		ep -- filled in with the pointer to the byte
467**			after the name.
468**
469**	Returns:
470**		0 -- An error was detected.
471**		1..255 -- The internal id code for this macro.
472**
473**	Side Effects:
474**		If this is a new macro name, a new id is allocated.
475**		On error, syserr is called.
476*/
477
478int
479macid_parse(p, ep)
480	register char *p;
481	char **ep;
482{
483	int mid;
484	register char *bp;
485	char mbuf[MAXMACNAMELEN + 1];
486
487	if (tTd(35, 14))
488	{
489		sm_dprintf("macid(");
490		xputs(p);
491		sm_dprintf(") => ");
492	}
493
494	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
495	{
496		syserr("Name required for macro/class");
497		if (ep != NULL)
498			*ep = p;
499		if (tTd(35, 14))
500			sm_dprintf("NULL\n");
501		return 0;
502	}
503	if (*p != '{')
504	{
505		/* the macro is its own code */
506		if (ep != NULL)
507			*ep = p + 1;
508		if (tTd(35, 14))
509			sm_dprintf("%c\n", bitidx(*p));
510		return bitidx(*p);
511	}
512	bp = mbuf;
513	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
514	{
515		if (isascii(*p) && (isalnum(*p) || *p == '_'))
516			*bp++ = *p;
517		else
518			syserr("Invalid macro/class character %c", *p);
519	}
520	*bp = '\0';
521	mid = -1;
522	if (*p == '\0')
523	{
524		syserr("Unbalanced { on %s", mbuf);	/* missing } */
525	}
526	else if (*p != '}')
527	{
528		syserr("Macro/class name ({%s}) too long (%d chars max)",
529			mbuf, (int) (sizeof mbuf - 1));
530	}
531	else if (mbuf[1] == '\0')
532	{
533		/* ${x} == $x */
534		mid = bitidx(mbuf[0]);
535		p++;
536	}
537	else
538	{
539		register STAB *s;
540
541		s = stab(mbuf, ST_MACRO, ST_ENTER);
542		if (s->s_macro != 0)
543			mid = s->s_macro;
544		else
545		{
546			if (NextMacroId > MAXMACROID)
547			{
548				syserr("Macro/class {%s}: too many long names",
549					mbuf);
550				s->s_macro = -1;
551			}
552			else
553			{
554				MacroName[NextMacroId] = s->s_name;
555				s->s_macro = mid = NextMacroId++;
556			}
557		}
558		p++;
559	}
560	if (ep != NULL)
561		*ep = p;
562	if (mid < 0 || mid > MAXMACROID)
563	{
564		syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
565		if (tTd(35, 14))
566			sm_dprintf("NULL\n");
567		return 0;
568	}
569	if (tTd(35, 14))
570		sm_dprintf("0x%x\n", mid);
571	return mid;
572}
573/*
574**  WORDINCLASS -- tell if a word is in a specific class
575**
576**	Parameters:
577**		str -- the name of the word to look up.
578**		cl -- the class name.
579**
580**	Returns:
581**		true if str can be found in cl.
582**		false otherwise.
583*/
584
585bool
586wordinclass(str, cl)
587	char *str;
588	int cl;
589{
590	register STAB *s;
591
592	s = stab(str, ST_CLASS, ST_FIND);
593	return s != NULL && bitnset(bitidx(cl), s->s_class);
594}
595