xref: /freebsd/contrib/sendmail/src/macro.c (revision 6780ab54325a71e7e70112b11657973edde8655e)
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 
16 SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro 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(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 
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(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 
368 void
369 macset(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 
403 char *
404 macvalue(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 
441 char *
442 macname(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 
478 int
479 macid_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 
585 bool
586 wordinclass(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