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