1 # include "sendmail.h"
2 
3 SCCSID(@(#)macro.c	3.16		09/05/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 **		End of interpolated output.
17 **
18 **	Side Effects:
19 **		none.
20 */
21 
22 expand(s, buf, buflim, e)
23 	register char *s;
24 	register char *buf;
25 	char *buflim;
26 	register ENVELOPE *e;
27 {
28 	extern char *expand2();
29 
30 	(void) expand2(s, buf, buflim, e);
31 }
32 
33 
34 char *
35 expand2(s, buf, buflim, e)
36 	register char *s;
37 	register char *buf;
38 	char *buflim;
39 	register ENVELOPE *e;
40 {
41 	register char *q;
42 	char xbuf[BUFSIZ];
43 	register char *xp = xbuf;
44 	bool skipping;		/* set if conditionally skipping output */
45 	bool gotone = FALSE;	/* set if any expansion done */
46 
47 # ifdef DEBUG
48 	if (tTd(35, 4))
49 	{
50 		printf("expand(");
51 		xputs(s);
52 		printf(")\n");
53 	}
54 # endif DEBUG
55 
56 	skipping = FALSE;
57 	if (s == NULL)
58 		s = "";
59 	for (; *s != '\0'; s++)
60 	{
61 		char c;
62 
63 		/*
64 		**  Check for non-ordinary (special?) character.
65 		**	'q' will be the interpolated quantity.
66 		*/
67 
68 		q = NULL;
69 		c = *s;
70 		switch (c)
71 		{
72 		  case CONDIF:		/* see if var set */
73 			c = *++s;
74 			skipping = e->e_macro[c] == NULL;
75 			continue;
76 
77 		  case CONDELSE:	/* change state of skipping */
78 			skipping = !skipping;
79 			continue;
80 
81 		  case CONDFI:		/* stop skipping */
82 			skipping = FALSE;
83 			continue;
84 
85 		  case '$':		/* macro interpolation */
86 			c = *++s;
87 			q = e->e_macro[c & 0177];
88 			if (q == NULL && c != '$')
89 				continue;
90 			gotone = TRUE;
91 			break;
92 		}
93 
94 		/*
95 		**  Interpolate q or output one character
96 		*/
97 
98 		if (skipping)
99 			continue;
100 		while (xp < &xbuf[sizeof xbuf])
101 		{
102 			if (q == NULL)
103 			{
104 				*xp++ = c;
105 				break;
106 			}
107 			if (*q == NULL)
108 				break;
109 			*xp++ = *q++;
110 		}
111 	}
112 	*xp = '\0';
113 
114 # ifdef DEBUG
115 	if (tTd(35, 4))
116 	{
117 		printf("expand ==> ");
118 		xputs(xbuf);
119 		printf("\n");
120 	}
121 # endif DEBUG
122 
123 	/* recurse as appropriate */
124 	if (gotone)
125 		return (expand2(xbuf, buf, buflim, e));
126 
127 	/* copy results out */
128 	for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
129 		*q++ = *xp++;
130 	*q = '\0';
131 
132 	return (q);
133 }
134 /*
135 **  DEFINE -- define a macro.
136 **
137 **	this would be better done using a #define macro.
138 **
139 **	Parameters:
140 **		n -- the macro name.
141 **		v -- the macro value.
142 **
143 **	Returns:
144 **		none.
145 **
146 **	Side Effects:
147 **		CurEnv->e_macro[n] is defined.
148 **
149 **	Notes:
150 **		There is one macro for each ASCII character,
151 **		although they are not all used.  The currently
152 **		defined macros are:
153 **
154 **		$a   date in ARPANET format (preferring the Date: line
155 **		     of the message)
156 **		$b   the current date (as opposed to the date as found
157 **		     the message) in ARPANET format
158 **		$c   hop count
159 **		$d   (current) date in UNIX (ctime) format
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 **		$x   signature (full name) of from person
178 **		$y   the tty id of our terminal
179 **		$z   home directory of to person
180 **
181 **		Macros marked with + must be defined in the
182 **		configuration file and are used internally, but
183 **		are not set.
184 **
185 **		There are also some macros that can be used
186 **		arbitrarily to make the configuration file
187 **		cleaner.  In general all upper-case letters
188 **		are available.
189 */
190 
191 define(n, v)
192 	char n;
193 	char *v;
194 {
195 # ifdef DEBUG
196 	if (tTd(35, 3))
197 	{
198 		printf("define(%c as ", n);
199 		xputs(v);
200 		printf(")\n");
201 	}
202 # endif DEBUG
203 	CurEnv->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)
220 	char n;
221 {
222 	return (CurEnv->e_macro[n & 0177]);
223 }
224