xref: /csrg-svn/usr.sbin/sendmail/src/macro.c (revision 10407)
1 # include "sendmail.h"
2 
3 SCCSID(@(#)macro.c	3.19		01/17/83);
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 **		$w   our host name (if it can be determined)
175 **		$x   signature (full name) of from person
176 **		$y   the tty id of our terminal
177 **		$z   home directory of to person
178 **
179 **		Macros marked with + must be defined in the
180 **		configuration file and are used internally, but
181 **		are not set.
182 **
183 **		There are also some macros that can be used
184 **		arbitrarily to make the configuration file
185 **		cleaner.  In general all upper-case letters
186 **		are available.
187 */
188 
189 define(n, v, e)
190 	char n;
191 	char *v;
192 	register ENVELOPE *e;
193 {
194 # ifdef DEBUG
195 	if (tTd(35, 3))
196 	{
197 		printf("define(%c as ", n);
198 		xputs(v);
199 		printf(")\n");
200 	}
201 # endif DEBUG
202 	e->e_macro[n & 0177] = v;
203 }
204 /*
205 **  MACVALUE -- return uninterpreted value of a macro.
206 **
207 **	Parameters:
208 **		n -- the name of the macro.
209 **
210 **	Returns:
211 **		The value of n.
212 **
213 **	Side Effects:
214 **		none.
215 */
216 
217 char *
218 macvalue(n, e)
219 	char n;
220 	register ENVELOPE *e;
221 {
222 	n &= 0177;
223 	while (e != NULL)
224 	{
225 		register char *p = e->e_macro[n];
226 
227 		if (p != NULL)
228 			return (p);
229 		e = e->e_parent;
230 	}
231 	return (NULL);
232 }
233