1 # include "sendmail.h"
2 
3 SCCSID(@(#)macro.c	3.13		05/31/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 (Debug > 3)
49 	{
50 		printf("expand(");
51 		xputs(s);
52 		printf(")\n");
53 	}
54 # endif DEBUG
55 
56 	skipping = FALSE;
57 	for (; *s != '\0'; s++)
58 	{
59 		char c;
60 
61 		/*
62 		**  Check for non-ordinary (special?) character.
63 		**	'q' will be the interpolated quantity.
64 		*/
65 
66 		q = NULL;
67 		c = *s;
68 		switch (c)
69 		{
70 		  case CONDIF:		/* see if var set */
71 			c = *++s;
72 			skipping = e->e_macro[c] == NULL;
73 			continue;
74 
75 		  case CONDELSE:	/* change state of skipping */
76 			skipping = !skipping;
77 			continue;
78 
79 		  case CONDFI:		/* stop skipping */
80 			skipping = FALSE;
81 			continue;
82 
83 		  case '$':		/* macro interpolation */
84 			c = *++s;
85 			q = e->e_macro[c & 0177];
86 			if (q == NULL && c != '$')
87 				continue;
88 			gotone = TRUE;
89 			break;
90 		}
91 
92 		/*
93 		**  Interpolate q or output one character
94 		*/
95 
96 		if (skipping)
97 			continue;
98 		while (xp < &xbuf[sizeof xbuf])
99 		{
100 			if (q == NULL)
101 			{
102 				*xp++ = c;
103 				break;
104 			}
105 			if (*q == NULL)
106 				break;
107 			*xp++ = *q++;
108 		}
109 	}
110 	*xp = '\0';
111 
112 # ifdef DEBUG
113 	if (Debug > 3)
114 	{
115 		printf("expand ==> '");
116 		xputs(xbuf);
117 		printf("'\n");
118 	}
119 # endif DEBUG
120 
121 	/* recurse as appropriate */
122 	if (gotone)
123 		return (expand2(xbuf, buf, buflim, e));
124 
125 	/* copy results out */
126 	for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; )
127 		*q++ = *xp++;
128 	*q = '\0';
129 
130 	return (q);
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 **
141 **	Returns:
142 **		none.
143 **
144 **	Side Effects:
145 **		CurEnv->e_macro[n] is defined.
146 **
147 **	Notes:
148 **		There is one macro for each ASCII character,
149 **		although they are not all used.  The currently
150 **		defined macros are:
151 **
152 **		$a   date in ARPANET format (preferring the Date: line
153 **		     of the message)
154 **		$b   the current date (as opposed to the date as found
155 **		     the message) in ARPANET format
156 **		$c   hop count
157 **		$d   (current) date in UNIX (ctime) format
158 **		$f   raw from address
159 **		$g   translated from address
160 **		$h   to host
161 **		$i   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)
189 	char n;
190 	char *v;
191 {
192 # ifdef DEBUG
193 	if (Debug > 3)
194 	{
195 		printf("define(%c as ", n);
196 		xputs(v);
197 		printf(")\n");
198 	}
199 # endif DEBUG
200 	CurEnv->e_macro[n & 0177] = v;
201 }
202 /*
203 **  MACVALUE -- return uninterpreted value of a macro.
204 **
205 **	Parameters:
206 **		n -- the name of the macro.
207 **
208 **	Returns:
209 **		The value of n.
210 **
211 **	Side Effects:
212 **		none.
213 */
214 
215 char *
216 macvalue(n)
217 	char n;
218 {
219 	return (CurEnv->e_macro[n & 0177]);
220 }
221