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