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