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