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