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