xref: /freebsd/contrib/sendmail/src/macro.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
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 #ifndef lint
15 static char id[] = "@(#)$Id: macro.c,v 8.40.16.9 2001/02/22 01:16:55 gshapiro Exp $";
16 #endif /* ! lint */
17 
18 #include <sendmail.h>
19 
20 #if MAXMACROID != (BITMAPBITS - 1)
21 	ERROR Read the comment in conf.h
22 #endif /* MAXMACROID != (BITMAPBITS - 1) */
23 
24 char	*MacroName[MAXMACROID + 1];	/* macro id to name table */
25 int	NextMacroId = 0240;		/* codes for long named macros */
26 
27 /*
28 **  EXPAND -- macro expand a string using $x escapes.
29 **
30 **	Parameters:
31 **		s -- the string to expand.
32 **		buf -- the place to put the expansion.
33 **		bufsize -- the size of the buffer.
34 **		e -- envelope in which to work.
35 **
36 **	Returns:
37 **		none.
38 **
39 **	Side Effects:
40 **		none.
41 */
42 
43 void
44 expand(s, buf, bufsize, e)
45 	register char *s;
46 	register char *buf;
47 	size_t bufsize;
48 	register ENVELOPE *e;
49 {
50 	register char *xp;
51 	register char *q;
52 	bool skipping;		/* set if conditionally skipping output */
53 	bool recurse = FALSE;	/* set if recursion required */
54 	int i;
55 	int skiplev;		/* skipping nesting level */
56 	int iflev;		/* if nesting level */
57 	char xbuf[MACBUFSIZE];
58 	static int explevel = 0;
59 
60 	if (tTd(35, 24))
61 	{
62 		dprintf("expand(");
63 		xputs(s);
64 		dprintf(")\n");
65 	}
66 
67 	skipping = FALSE;
68 	skiplev = 0;
69 	iflev = 0;
70 	if (s == NULL)
71 		s = "";
72 	for (xp = xbuf; *s != '\0'; s++)
73 	{
74 		int c;
75 
76 		/*
77 		**  Check for non-ordinary (special?) character.
78 		**	'q' will be the interpolated quantity.
79 		*/
80 
81 		q = NULL;
82 		c = *s;
83 		switch (c & 0377)
84 		{
85 		  case CONDIF:		/* see if var set */
86 			iflev++;
87 			c = *++s;
88 			if (skipping)
89 				skiplev++;
90 			else
91 			{
92 				char *mv;
93 
94 				mv = macvalue(c, e);
95 				skipping = (mv == NULL || *mv == '\0');
96 			}
97 			continue;
98 
99 		  case CONDELSE:	/* change state of skipping */
100 			if (iflev == 0)
101 				break;
102 			if (skiplev == 0)
103 				skipping = !skipping;
104 			continue;
105 
106 		  case CONDFI:		/* stop skipping */
107 			if (iflev == 0)
108 				break;
109 			iflev--;
110 			if (skiplev == 0)
111 				skipping = FALSE;
112 			if (skipping)
113 				skiplev--;
114 			continue;
115 
116 		  case MACROEXPAND:	/* macro interpolation */
117 			c = bitidx(*++s);
118 			if (c != '\0')
119 				q = macvalue(c, e);
120 			else
121 			{
122 				s--;
123 				q = NULL;
124 			}
125 			if (q == NULL)
126 				continue;
127 			break;
128 		}
129 
130 		/*
131 		**  Interpolate q or output one character
132 		*/
133 
134 		if (skipping || xp >= &xbuf[sizeof xbuf - 1])
135 			continue;
136 		if (q == NULL)
137 			*xp++ = c;
138 		else
139 		{
140 			/* copy to end of q or max space remaining in buf */
141 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
142 			{
143 				/* check for any sendmail metacharacters */
144 				if ((c & 0340) == 0200)
145 					recurse = TRUE;
146 				*xp++ = c;
147 			}
148 		}
149 	}
150 	*xp = '\0';
151 
152 	if (tTd(35, 24))
153 	{
154 		dprintf("expand ==> ");
155 		xputs(xbuf);
156 		dprintf("\n");
157 	}
158 
159 	/* recurse as appropriate */
160 	if (recurse)
161 	{
162 		if (explevel < MaxMacroRecursion)
163 		{
164 			explevel++;
165 			expand(xbuf, buf, bufsize, e);
166 			explevel--;
167 			return;
168 		}
169 		syserr("expand: recursion too deep (%d max)",
170 			MaxMacroRecursion);
171 	}
172 
173 	/* copy results out */
174 	i = xp - xbuf;
175 	if ((size_t)i >= bufsize)
176 		i = bufsize - 1;
177 	memmove(buf, xbuf, i);
178 	buf[i] = '\0';
179 }
180 /*
181 **  DEFINE -- define a macro.
182 **
183 **	this would be better done using a #define macro.
184 **
185 **	Parameters:
186 **		n -- the macro name.
187 **		v -- the macro value.
188 **		e -- the envelope to store the definition in.
189 **
190 **	Returns:
191 **		none.
192 **
193 **	Side Effects:
194 **		e->e_macro[n] is defined.
195 **
196 **	Notes:
197 **		There is one macro for each ASCII character,
198 **		although they are not all used.  The currently
199 **		defined macros are:
200 **
201 **		$a   date in ARPANET format (preferring the Date: line
202 **		     of the message)
203 **		$b   the current date (as opposed to the date as found
204 **		     the message) in ARPANET format
205 **		$c   hop count
206 **		$d   (current) date in UNIX (ctime) format
207 **		$e   the SMTP entry message+
208 **		$f   raw from address
209 **		$g   translated from address
210 **		$h   to host
211 **		$i   queue id
212 **		$j   official SMTP hostname, used in messages+
213 **		$k   UUCP node name
214 **		$l   UNIX-style from line+
215 **		$m   The domain part of our full name.
216 **		$n   name of sendmail ("MAILER-DAEMON" on local
217 **		     net typically)+
218 **		$o   delimiters ("operators") for address tokens+
219 **		     (set via OperatorChars option in V6 or later
220 **		      sendmail.cf files)
221 **		$p   my process id in decimal
222 **		$q   the string that becomes an address -- this is
223 **		     normally used to combine $g & $x.
224 **		$r   protocol used to talk to sender
225 **		$s   sender's host name
226 **		$t   the current time in seconds since 1/1/1970
227 **		$u   to user
228 **		$v   version number of sendmail
229 **		$w   our host name (if it can be determined)
230 **		$x   signature (full name) of from person
231 **		$y   the tty id of our terminal
232 **		$z   home directory of to person
233 **		$_   RFC1413 authenticated sender address
234 **
235 **		Macros marked with + must be defined in the
236 **		configuration file and are used internally, but
237 **		are not set.
238 **
239 **		There are also some macros that can be used
240 **		arbitrarily to make the configuration file
241 **		cleaner.  In general all upper-case letters
242 **		are available.
243 */
244 
245 void
246 define(n, v, e)
247 	int n;
248 	char *v;
249 	register ENVELOPE *e;
250 {
251 	int m;
252 
253 	m = bitidx(n);
254 	if (tTd(35, 9))
255 	{
256 		dprintf("%sdefine(%s as ",
257 			(e->e_macro[m] == NULL) ? ""
258 						: "re", macname(n));
259 		xputs(v);
260 		dprintf(")\n");
261 	}
262 	e->e_macro[m] = v;
263 
264 #if _FFR_RESET_MACRO_GLOBALS
265 	switch (m)
266 	{
267 	  case 'j':
268 		MyHostName = v;
269 		break;
270 	}
271 #endif /* _FFR_RESET_MACRO_GLOBALS */
272 }
273 /*
274 **  MACVALUE -- return uninterpreted value of a macro.
275 **
276 **	Parameters:
277 **		n -- the name of the macro.
278 **
279 **	Returns:
280 **		The value of n.
281 **
282 **	Side Effects:
283 **		none.
284 */
285 
286 char *
287 macvalue(n, e)
288 	int n;
289 	register ENVELOPE *e;
290 {
291 	n = bitidx(n);
292 	while (e != NULL)
293 	{
294 		register char *p = e->e_macro[n];
295 
296 		if (p != NULL)
297 			return p;
298 		if (e == e->e_parent)
299 			break;
300 		e = e->e_parent;
301 	}
302 	return NULL;
303 }
304 /*
305 **  MACNAME -- return the name of a macro given its internal id
306 **
307 **	Parameter:
308 **		n -- the id of the macro
309 **
310 **	Returns:
311 **		The name of n.
312 **
313 **	Side Effects:
314 **		none.
315 */
316 
317 char *
318 macname(n)
319 	int n;
320 {
321 	static char mbuf[2];
322 
323 	n = bitidx(n);
324 	if (bitset(0200, n))
325 	{
326 		char *p = MacroName[n];
327 
328 		if (p != NULL)
329 			return p;
330 		return "***UNDEFINED MACRO***";
331 	}
332 	mbuf[0] = n;
333 	mbuf[1] = '\0';
334 	return mbuf;
335 }
336 /*
337 **  MACID -- return id of macro identified by its name
338 **
339 **	Parameters:
340 **		p -- pointer to name string -- either a single
341 **			character or {name}.
342 **		ep -- filled in with the pointer to the byte
343 **			after the name.
344 **
345 **	Returns:
346 **		The internal id code for this macro.  This will
347 **		fit into a single byte.
348 **
349 **	Side Effects:
350 **		If this is a new macro name, a new id is allocated.
351 */
352 
353 int
354 macid(p, ep)
355 	register char *p;
356 	char **ep;
357 {
358 	int mid;
359 	register char *bp;
360 	char mbuf[MAXMACNAMELEN + 1];
361 
362 	if (tTd(35, 14))
363 	{
364 		dprintf("macid(");
365 		xputs(p);
366 		dprintf(") => ");
367 	}
368 
369 	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
370 	{
371 		syserr("Name required for macro/class");
372 		if (ep != NULL)
373 			*ep = p;
374 		if (tTd(35, 14))
375 			dprintf("NULL\n");
376 		return 0;
377 	}
378 	if (*p != '{')
379 	{
380 		/* the macro is its own code */
381 		if (ep != NULL)
382 			*ep = p + 1;
383 		if (tTd(35, 14))
384 			dprintf("%c\n", bitidx(*p));
385 		return bitidx(*p);
386 	}
387 	bp = mbuf;
388 	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
389 	{
390 		if (isascii(*p) && (isalnum(*p) || *p == '_'))
391 			*bp++ = *p;
392 		else
393 			syserr("Invalid macro/class character %c", *p);
394 	}
395 	*bp = '\0';
396 	mid = -1;
397 	if (*p == '\0')
398 	{
399 		syserr("Unbalanced { on %s", mbuf);	/* missing } */
400 	}
401 	else if (*p != '}')
402 	{
403 		syserr("Macro/class name ({%s}) too long (%d chars max)",
404 			mbuf, sizeof mbuf - 1);
405 	}
406 	else if (mbuf[1] == '\0')
407 	{
408 		/* ${x} == $x */
409 		mid = bitidx(mbuf[0]);
410 		p++;
411 	}
412 	else
413 	{
414 		register STAB *s;
415 
416 		s = stab(mbuf, ST_MACRO, ST_ENTER);
417 		if (s->s_macro != 0)
418 			mid = s->s_macro;
419 		else
420 		{
421 			if (NextMacroId > MAXMACROID)
422 			{
423 				syserr("Macro/class {%s}: too many long names", mbuf);
424 				s->s_macro = -1;
425 			}
426 			else
427 			{
428 				MacroName[NextMacroId] = s->s_name;
429 				s->s_macro = mid = NextMacroId++;
430 			}
431 		}
432 		p++;
433 	}
434 	if (ep != NULL)
435 		*ep = p;
436 	if (mid < 0 || mid > MAXMACROID)
437 	{
438 		syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
439 		if (tTd(35, 14))
440 			dprintf("NULL\n");
441 		return 0;
442 	}
443 	if (tTd(35, 14))
444 		dprintf("0x%x\n", mid);
445 	return mid;
446 }
447 /*
448 **  WORDINCLASS -- tell if a word is in a specific class
449 **
450 **	Parameters:
451 **		str -- the name of the word to look up.
452 **		cl -- the class name.
453 **
454 **	Returns:
455 **		TRUE if str can be found in cl.
456 **		FALSE otherwise.
457 */
458 
459 bool
460 wordinclass(str, cl)
461 	char *str;
462 	int cl;
463 {
464 	register STAB *s;
465 
466 	s = stab(str, ST_CLASS, ST_FIND);
467 	return s != NULL && bitnset(bitidx(cl), s->s_class);
468 }
469