xref: /freebsd/contrib/sendmail/src/macro.c (revision d056fa046c6a91b90cd98165face0e42a33a5173)
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 
16 SM_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 
22 static char	*MacroName[MAXMACROID + 1];	/* macro id to name table */
23 int		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 
41 struct 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 
68 void
69 initmacros(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 
113 void
114 expand(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 
283 void
284 #if SM_HEAP_CHECK
285 macdefine_tagged(mac, vclass, id, value, file, line, grp)
286 #else /* SM_HEAP_CHECK */
287 macdefine(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 
372 void
373 macset(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 
407 char *
408 macvalue(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 
445 char *
446 macname(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 
482 int
483 macid_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 
589 bool
590 wordinclass(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