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