xref: /freebsd/contrib/sendmail/src/macro.c (revision 5069714534cba67f1985e6dfe23b145178372b5f)
1 /*
2  * Copyright (c) 1998-2000 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.7 2000/10/09 15:49:06 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 		e = e->e_parent;
299 	}
300 	return NULL;
301 }
302 /*
303 **  MACNAME -- return the name of a macro given its internal id
304 **
305 **	Parameter:
306 **		n -- the id of the macro
307 **
308 **	Returns:
309 **		The name of n.
310 **
311 **	Side Effects:
312 **		none.
313 */
314 
315 char *
316 macname(n)
317 	int n;
318 {
319 	static char mbuf[2];
320 
321 	n = bitidx(n);
322 	if (bitset(0200, n))
323 	{
324 		char *p = MacroName[n];
325 
326 		if (p != NULL)
327 			return p;
328 		return "***UNDEFINED MACRO***";
329 	}
330 	mbuf[0] = n;
331 	mbuf[1] = '\0';
332 	return mbuf;
333 }
334 /*
335 **  MACID -- return id of macro identified by its name
336 **
337 **	Parameters:
338 **		p -- pointer to name string -- either a single
339 **			character or {name}.
340 **		ep -- filled in with the pointer to the byte
341 **			after the name.
342 **
343 **	Returns:
344 **		The internal id code for this macro.  This will
345 **		fit into a single byte.
346 **
347 **	Side Effects:
348 **		If this is a new macro name, a new id is allocated.
349 */
350 
351 int
352 macid(p, ep)
353 	register char *p;
354 	char **ep;
355 {
356 	int mid;
357 	register char *bp;
358 	char mbuf[MAXMACNAMELEN + 1];
359 
360 	if (tTd(35, 14))
361 	{
362 		dprintf("macid(");
363 		xputs(p);
364 		dprintf(") => ");
365 	}
366 
367 	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
368 	{
369 		syserr("Name required for macro/class");
370 		if (ep != NULL)
371 			*ep = p;
372 		if (tTd(35, 14))
373 			dprintf("NULL\n");
374 		return 0;
375 	}
376 	if (*p != '{')
377 	{
378 		/* the macro is its own code */
379 		if (ep != NULL)
380 			*ep = p + 1;
381 		if (tTd(35, 14))
382 			dprintf("%c\n", bitidx(*p));
383 		return bitidx(*p);
384 	}
385 	bp = mbuf;
386 	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
387 	{
388 		if (isascii(*p) && (isalnum(*p) || *p == '_'))
389 			*bp++ = *p;
390 		else
391 			syserr("Invalid macro/class character %c", *p);
392 	}
393 	*bp = '\0';
394 	mid = -1;
395 	if (*p == '\0')
396 	{
397 		syserr("Unbalanced { on %s", mbuf);	/* missing } */
398 	}
399 	else if (*p != '}')
400 	{
401 		syserr("Macro/class name ({%s}) too long (%d chars max)",
402 			mbuf, sizeof mbuf - 1);
403 	}
404 	else if (mbuf[1] == '\0')
405 	{
406 		/* ${x} == $x */
407 		mid = bitidx(mbuf[0]);
408 		p++;
409 	}
410 	else
411 	{
412 		register STAB *s;
413 
414 		s = stab(mbuf, ST_MACRO, ST_ENTER);
415 		if (s->s_macro != 0)
416 			mid = s->s_macro;
417 		else
418 		{
419 			if (NextMacroId > MAXMACROID)
420 			{
421 				syserr("Macro/class {%s}: too many long names", mbuf);
422 				s->s_macro = -1;
423 			}
424 			else
425 			{
426 				MacroName[NextMacroId] = s->s_name;
427 				s->s_macro = mid = NextMacroId++;
428 			}
429 		}
430 		p++;
431 	}
432 	if (ep != NULL)
433 		*ep = p;
434 	if (mid < 0 || mid > MAXMACROID)
435 	{
436 		syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
437 		if (tTd(35, 14))
438 			dprintf("NULL\n");
439 		return 0;
440 	}
441 	if (tTd(35, 14))
442 		dprintf("0x%x\n", mid);
443 	return mid;
444 }
445 /*
446 **  WORDINCLASS -- tell if a word is in a specific class
447 **
448 **	Parameters:
449 **		str -- the name of the word to look up.
450 **		cl -- the class name.
451 **
452 **	Returns:
453 **		TRUE if str can be found in cl.
454 **		FALSE otherwise.
455 */
456 
457 bool
458 wordinclass(str, cl)
459 	char *str;
460 	int cl;
461 {
462 	register STAB *s;
463 
464 	s = stab(str, ST_CLASS, ST_FIND);
465 	return s != NULL && bitnset(bitidx(cl), s->s_class);
466 }
467