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