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