xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 34921)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that the above copyright notice and this paragraph are
8  * duplicated in all such forms and that any documentation,
9  * advertising materials, and other materials related to such
10  * distribution and use acknowledge that the software was developed
11  * by the University of California, Berkeley.  The name of the
12  * University may not be used to endorse or promote products derived
13  * from this software without specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 #ifndef lint
20 static char sccsid[] = "@(#)macro.c	5.5 (Berkeley) 06/30/88";
21 #endif /* not lint */
22 
23 # include "sendmail.h"
24 
25 /*
26 **  EXPAND -- macro expand a string using $x escapes.
27 **
28 **	Parameters:
29 **		s -- the string to expand.
30 **		buf -- the place to put the expansion.
31 **		buflim -- the buffer limit, i.e., the address
32 **			of the last usable position in buf.
33 **		e -- envelope in which to work.
34 **
35 **	Returns:
36 **		none.
37 **
38 **	Side Effects:
39 **		none.
40 */
41 
42 expand(s, buf, buflim, e)
43 	register char *s;
44 	register char *buf;
45 	char *buflim;
46 	register ENVELOPE *e;
47 {
48 	register char *xp;
49 	register char *q;
50 	bool skipping;		/* set if conditionally skipping output */
51 	bool recurse = FALSE;	/* set if recursion required */
52 	int i;
53 	char xbuf[BUFSIZ];
54 	extern char *macvalue();
55 
56 # ifdef DEBUG
57 	if (tTd(35, 24))
58 	{
59 		printf("expand(");
60 		xputs(s);
61 		printf(")\n");
62 	}
63 # endif DEBUG
64 
65 	skipping = FALSE;
66 	if (s == NULL)
67 		s = "";
68 	for (xp = xbuf; *s != '\0'; s++)
69 	{
70 		char 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)
80 		{
81 		  case CONDIF:		/* see if var set */
82 			c = *++s;
83 			skipping = macvalue(c, e) == NULL;
84 			continue;
85 
86 		  case CONDELSE:	/* change state of skipping */
87 			skipping = !skipping;
88 			continue;
89 
90 		  case CONDFI:		/* stop skipping */
91 			skipping = FALSE;
92 			continue;
93 
94 		  case '\001':		/* macro interpolation */
95 			c = *++s;
96 			q = macvalue(c & 0177, e);
97 			if (q == NULL)
98 				continue;
99 			break;
100 		}
101 
102 		/*
103 		**  Interpolate q or output one character
104 		*/
105 
106 		if (skipping || xp >= &xbuf[sizeof xbuf])
107 			continue;
108 		if (q == NULL)
109 			*xp++ = c;
110 		else
111 		{
112 			/* copy to end of q or max space remaining in buf */
113 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
114 			{
115 				if (iscntrl(c) && !isspace(c))
116 					recurse = TRUE;
117 				*xp++ = c;
118 			}
119 		}
120 	}
121 	*xp = '\0';
122 
123 # ifdef DEBUG
124 	if (tTd(35, 24))
125 	{
126 		printf("expand ==> ");
127 		xputs(xbuf);
128 		printf("\n");
129 	}
130 # endif DEBUG
131 
132 	/* recurse as appropriate */
133 	if (recurse)
134 	{
135 		expand(xbuf, buf, buflim, e);
136 		return;
137 	}
138 
139 	/* copy results out */
140 	i = buflim - buf - 1;
141 	if (i > xp - xbuf)
142 		i = xp - xbuf;
143 	bcopy(xbuf, buf, i);
144 	buf[i] = '\0';
145 }
146 /*
147 **  DEFINE -- define a macro.
148 **
149 **	this would be better done using a #define macro.
150 **
151 **	Parameters:
152 **		n -- the macro name.
153 **		v -- the macro value.
154 **		e -- the envelope to store the definition in.
155 **
156 **	Returns:
157 **		none.
158 **
159 **	Side Effects:
160 **		e->e_macro[n] is defined.
161 **
162 **	Notes:
163 **		There is one macro for each ASCII character,
164 **		although they are not all used.  The currently
165 **		defined macros are:
166 **
167 **		$a   date in ARPANET format (preferring the Date: line
168 **		     of the message)
169 **		$b   the current date (as opposed to the date as found
170 **		     the message) in ARPANET format
171 **		$c   hop count
172 **		$d   (current) date in UNIX (ctime) format
173 **		$e   the SMTP entry message+
174 **		$f   raw from address
175 **		$g   translated from address
176 **		$h   to host
177 **		$i   queue id
178 **		$j   official SMTP hostname, used in messages+
179 **		$l   UNIX-style from line+
180 **		$n   name of sendmail ("MAILER-DAEMON" on local
181 **		     net typically)+
182 **		$o   delimiters ("operators") for address tokens+
183 **		$p   my process id in decimal
184 **		$q   the string that becomes an address -- this is
185 **		     normally used to combine $g & $x.
186 **		$r   protocol used to talk to sender
187 **		$s   sender's host name
188 **		$t   the current time in seconds since 1/1/1970
189 **		$u   to user
190 **		$v   version number of sendmail
191 **		$w   our host name (if it can be determined)
192 **		$x   signature (full name) of from person
193 **		$y   the tty id of our terminal
194 **		$z   home directory of to person
195 **
196 **		Macros marked with + must be defined in the
197 **		configuration file and are used internally, but
198 **		are not set.
199 **
200 **		There are also some macros that can be used
201 **		arbitrarily to make the configuration file
202 **		cleaner.  In general all upper-case letters
203 **		are available.
204 */
205 
206 define(n, v, e)
207 	char n;
208 	char *v;
209 	register ENVELOPE *e;
210 {
211 # ifdef DEBUG
212 	if (tTd(35, 9))
213 	{
214 		printf("define(%c as ", n);
215 		xputs(v);
216 		printf(")\n");
217 	}
218 # endif DEBUG
219 	e->e_macro[n & 0177] = v;
220 }
221 /*
222 **  MACVALUE -- return uninterpreted value of a macro.
223 **
224 **	Parameters:
225 **		n -- the name of the macro.
226 **
227 **	Returns:
228 **		The value of n.
229 **
230 **	Side Effects:
231 **		none.
232 */
233 
234 char *
235 macvalue(n, e)
236 	char n;
237 	register ENVELOPE *e;
238 {
239 	n &= 0177;
240 	while (e != NULL)
241 	{
242 		register char *p = e->e_macro[n];
243 
244 		if (p != NULL)
245 			return (p);
246 		e = e->e_parent;
247 	}
248 	return (NULL);
249 }
250