xref: /original-bsd/usr.sbin/sendmail/src/macro.c (revision abd50c55)
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.6 (Berkeley) 01/01/89";
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 	if (tTd(35, 24))
57 	{
58 		printf("expand(");
59 		xputs(s);
60 		printf(")\n");
61 	}
62 
63 	skipping = FALSE;
64 	if (s == NULL)
65 		s = "";
66 	for (xp = xbuf; *s != '\0'; s++)
67 	{
68 		char c;
69 
70 		/*
71 		**  Check for non-ordinary (special?) character.
72 		**	'q' will be the interpolated quantity.
73 		*/
74 
75 		q = NULL;
76 		c = *s;
77 		switch (c)
78 		{
79 		  case CONDIF:		/* see if var set */
80 			c = *++s;
81 			skipping = macvalue(c, e) == NULL;
82 			continue;
83 
84 		  case CONDELSE:	/* change state of skipping */
85 			skipping = !skipping;
86 			continue;
87 
88 		  case CONDFI:		/* stop skipping */
89 			skipping = FALSE;
90 			continue;
91 
92 		  case '\001':		/* macro interpolation */
93 			c = *++s;
94 			q = macvalue(c & 0177, e);
95 			if (q == NULL)
96 				continue;
97 			break;
98 		}
99 
100 		/*
101 		**  Interpolate q or output one character
102 		*/
103 
104 		if (skipping || xp >= &xbuf[sizeof xbuf])
105 			continue;
106 		if (q == NULL)
107 			*xp++ = c;
108 		else
109 		{
110 			/* copy to end of q or max space remaining in buf */
111 			while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
112 			{
113 				if (iscntrl(c) && !isspace(c))
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 **		$l   UNIX-style from line+
176 **		$n   name of sendmail ("MAILER-DAEMON" on local
177 **		     net typically)+
178 **		$o   delimiters ("operators") for address tokens+
179 **		$p   my process id in decimal
180 **		$q   the string that becomes an address -- this is
181 **		     normally used to combine $g & $x.
182 **		$r   protocol used to talk to sender
183 **		$s   sender's host name
184 **		$t   the current time in seconds since 1/1/1970
185 **		$u   to user
186 **		$v   version number of sendmail
187 **		$w   our host name (if it can be determined)
188 **		$x   signature (full name) of from person
189 **		$y   the tty id of our terminal
190 **		$z   home directory of to person
191 **
192 **		Macros marked with + must be defined in the
193 **		configuration file and are used internally, but
194 **		are not set.
195 **
196 **		There are also some macros that can be used
197 **		arbitrarily to make the configuration file
198 **		cleaner.  In general all upper-case letters
199 **		are available.
200 */
201 
202 define(n, v, e)
203 	char n;
204 	char *v;
205 	register ENVELOPE *e;
206 {
207 	if (tTd(35, 9))
208 	{
209 		printf("define(%c as ", n);
210 		xputs(v);
211 		printf(")\n");
212 	}
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