xref: /original-bsd/usr.sbin/sendmail/src/macro.c (revision 241757c4)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  *
12  *  Sendmail
13  *  Copyright (c) 1983  Eric P. Allman
14  *  Berkeley, California
15  */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)macro.c	5.4 (Berkeley) 03/13/88";
19 #endif /* not lint */
20 
21 # include "sendmail.h"
22 
23 /*
24 **  EXPAND -- macro expand a string using $x escapes.
25 **
26 **	Parameters:
27 **		s -- the string to expand.
28 **		buf -- the place to put the expansion.
29 **		buflim -- the buffer limit, i.e., the address
30 **			of the last usable position in buf.
31 **		e -- envelope in which to work.
32 **
33 **	Returns:
34 **		none.
35 **
36 **	Side Effects:
37 **		none.
38 */
39 
40 expand(s, buf, buflim, e)
41 	register char *s;
42 	register char *buf;
43 	char *buflim;
44 	register ENVELOPE *e;
45 {
46 	register char *xp;
47 	register char *q;
48 	bool skipping;		/* set if conditionally skipping output */
49 	bool recurse = FALSE;	/* set if recursion required */
50 	int i;
51 	char xbuf[BUFSIZ];
52 	extern char *macvalue();
53 
54 # ifdef DEBUG
55 	if (tTd(35, 24))
56 	{
57 		printf("expand(");
58 		xputs(s);
59 		printf(")\n");
60 	}
61 # endif DEBUG
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 # ifdef DEBUG
122 	if (tTd(35, 24))
123 	{
124 		printf("expand ==> ");
125 		xputs(xbuf);
126 		printf("\n");
127 	}
128 # endif DEBUG
129 
130 	/* recurse as appropriate */
131 	if (recurse)
132 	{
133 		expand(xbuf, buf, buflim, e);
134 		return;
135 	}
136 
137 	/* copy results out */
138 	i = buflim - buf - 1;
139 	if (i > xp - xbuf)
140 		i = xp - xbuf;
141 	bcopy(xbuf, buf, i);
142 	buf[i] = '\0';
143 }
144 /*
145 **  DEFINE -- define a macro.
146 **
147 **	this would be better done using a #define macro.
148 **
149 **	Parameters:
150 **		n -- the macro name.
151 **		v -- the macro value.
152 **		e -- the envelope to store the definition in.
153 **
154 **	Returns:
155 **		none.
156 **
157 **	Side Effects:
158 **		e->e_macro[n] is defined.
159 **
160 **	Notes:
161 **		There is one macro for each ASCII character,
162 **		although they are not all used.  The currently
163 **		defined macros are:
164 **
165 **		$a   date in ARPANET format (preferring the Date: line
166 **		     of the message)
167 **		$b   the current date (as opposed to the date as found
168 **		     the message) in ARPANET format
169 **		$c   hop count
170 **		$d   (current) date in UNIX (ctime) format
171 **		$e   the SMTP entry message+
172 **		$f   raw from address
173 **		$g   translated from address
174 **		$h   to host
175 **		$i   queue id
176 **		$j   official SMTP hostname, used in messages+
177 **		$l   UNIX-style from line+
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 **
194 **		Macros marked with + must be defined in the
195 **		configuration file and are used internally, but
196 **		are not set.
197 **
198 **		There are also some macros that can be used
199 **		arbitrarily to make the configuration file
200 **		cleaner.  In general all upper-case letters
201 **		are available.
202 */
203 
204 define(n, v, e)
205 	char n;
206 	char *v;
207 	register ENVELOPE *e;
208 {
209 # ifdef DEBUG
210 	if (tTd(35, 9))
211 	{
212 		printf("define(%c as ", n);
213 		xputs(v);
214 		printf(")\n");
215 	}
216 # endif DEBUG
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 	char 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