xref: /freebsd/contrib/sendmail/src/macro.c (revision d39bd2c1)
1c2aa98e2SPeter Wemm /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 1998-2001, 2003, 2006, 2007 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
15c2aa98e2SPeter Wemm 
164313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: macro.c,v 8.108 2013-11-22 20:51:55 ca Exp $")
1740266059SGregory Neil Shapiro 
18d0cef73dSGregory Neil Shapiro #include <sm/sendmail.h>
19193538b7SGregory Neil Shapiro #if MAXMACROID != (BITMAPBITS - 1)
20193538b7SGregory Neil Shapiro 	ERROR Read the comment in conf.h
215b0945b5SGregory Neil Shapiro #endif
22c2aa98e2SPeter Wemm 
2340266059SGregory Neil Shapiro static char	*MacroName[MAXMACROID + 1];	/* macro id to name table */
24ffb83623SGregory Neil Shapiro 
25ffb83623SGregory Neil Shapiro /*
26ffb83623SGregory Neil Shapiro **  Codes for long named macros.
27ffb83623SGregory Neil Shapiro **  See also macname():
28ffb83623SGregory Neil Shapiro 	* if not ASCII printable, look up the name *
29ffb83623SGregory Neil Shapiro 	if (n <= 0x20 || n > 0x7f)
30ffb83623SGregory Neil Shapiro **  First use 1 to NEXTMACROID_L, then use NEXTMACROID_H to MAXMACROID.
31ffb83623SGregory Neil Shapiro */
32ffb83623SGregory Neil Shapiro 
33ffb83623SGregory Neil Shapiro #define NEXTMACROID_L 037
34ffb83623SGregory Neil Shapiro #define NEXTMACROID_H 0240
35ffb83623SGregory Neil Shapiro 
36ffb83623SGregory Neil Shapiro #if _FFR_MORE_MACROS
37ffb83623SGregory Neil Shapiro /* table for next id in non-printable ASCII range: disallow some value */
38ffb83623SGregory Neil Shapiro static int NextMIdTable[] =
39ffb83623SGregory Neil Shapiro {
40ffb83623SGregory Neil Shapiro 	/*  0  nul */	 1,
41ffb83623SGregory Neil Shapiro 	/*  1  soh */	 2,
42ffb83623SGregory Neil Shapiro 	/*  2  stx */	 3,
43ffb83623SGregory Neil Shapiro 	/*  3  etx */	 4,
44ffb83623SGregory Neil Shapiro 	/*  4  eot */	 5,
45ffb83623SGregory Neil Shapiro 	/*  5  enq */	 6,
46ffb83623SGregory Neil Shapiro 	/*  6  ack */	 7,
47ffb83623SGregory Neil Shapiro 	/*  7  bel */	 8,
48ffb83623SGregory Neil Shapiro 	/*  8  bs  */	14,
49ffb83623SGregory Neil Shapiro 	/*  9  ht  */	-1,
50ffb83623SGregory Neil Shapiro 	/* 10  nl  */	-1,
51ffb83623SGregory Neil Shapiro 	/* 11  vt  */	-1,
52ffb83623SGregory Neil Shapiro 	/* 12  np  */	-1,
53ffb83623SGregory Neil Shapiro 	/* 13  cr  */	-1,
54ffb83623SGregory Neil Shapiro 	/* 14  so  */	15,
55ffb83623SGregory Neil Shapiro 	/* 15  si  */	16,
56ffb83623SGregory Neil Shapiro 	/* 16  dle */	17,
57ffb83623SGregory Neil Shapiro 	/* 17  dc1 */	18,
58ffb83623SGregory Neil Shapiro 	/* 18  dc2 */	19,
59ffb83623SGregory Neil Shapiro 	/* 19  dc3 */	20,
60ffb83623SGregory Neil Shapiro 	/* 20  dc4 */	21,
61ffb83623SGregory Neil Shapiro 	/* 21  nak */	22,
62ffb83623SGregory Neil Shapiro 	/* 22  syn */	23,
63ffb83623SGregory Neil Shapiro 	/* 23  etb */	24,
64ffb83623SGregory Neil Shapiro 	/* 24  can */	25,
65ffb83623SGregory Neil Shapiro 	/* 25  em  */	26,
66ffb83623SGregory Neil Shapiro 	/* 26  sub */	27,
67ffb83623SGregory Neil Shapiro 	/* 27  esc */	28,
68ffb83623SGregory Neil Shapiro 	/* 28  fs  */	29,
69ffb83623SGregory Neil Shapiro 	/* 29  gs  */	30,
70ffb83623SGregory Neil Shapiro 	/* 30  rs  */	31,
71ffb83623SGregory Neil Shapiro 	/* 31  us  */	32,
72ffb83623SGregory Neil Shapiro 	/* 32  sp  */	-1,
73ffb83623SGregory Neil Shapiro };
74ffb83623SGregory Neil Shapiro 
75ffb83623SGregory Neil Shapiro #define NEXTMACROID(mid)	(		\
76ffb83623SGregory Neil Shapiro 	(mid < NEXTMACROID_L) ? (NextMIdTable[mid]) :	\
77ffb83623SGregory Neil Shapiro 	((mid < NEXTMACROID_H) ? NEXTMACROID_H : (mid + 1)))
78ffb83623SGregory Neil Shapiro 
79ffb83623SGregory Neil Shapiro int		NextMacroId = 1;	/* codes for long named macros */
80d0cef73dSGregory Neil Shapiro /* see sendmail.h: Special characters in rewriting rules. */
81ffb83623SGregory Neil Shapiro #else /* _FFR_MORE_MACROS */
82ffb83623SGregory Neil Shapiro int		NextMacroId = 0240;	/* codes for long named macros */
83ffb83623SGregory Neil Shapiro #define NEXTMACROID(mid)	((mid) + 1)
84ffb83623SGregory Neil Shapiro #endif /* _FFR_MORE_MACROS */
85d0cef73dSGregory Neil Shapiro 
86c2aa98e2SPeter Wemm /*
8740266059SGregory Neil Shapiro **  INITMACROS -- initialize the macro system
8840266059SGregory Neil Shapiro **
8940266059SGregory Neil Shapiro **	This just involves defining some macros that are actually
9040266059SGregory Neil Shapiro **	used internally as metasymbols to be themselves.
9140266059SGregory Neil Shapiro **
9240266059SGregory Neil Shapiro **	Parameters:
9340266059SGregory Neil Shapiro **		none.
9440266059SGregory Neil Shapiro **
9540266059SGregory Neil Shapiro **	Returns:
9640266059SGregory Neil Shapiro **		none.
9740266059SGregory Neil Shapiro **
9840266059SGregory Neil Shapiro **	Side Effects:
9940266059SGregory Neil Shapiro **		initializes several macros to be themselves.
10040266059SGregory Neil Shapiro */
10140266059SGregory Neil Shapiro 
10240266059SGregory Neil Shapiro struct metamac	MetaMacros[] =
10340266059SGregory Neil Shapiro {
10440266059SGregory Neil Shapiro 	/* LHS pattern matching characters */
10540266059SGregory Neil Shapiro 	{ '*', MATCHZANY },	{ '+', MATCHANY },	{ '-', MATCHONE },
10640266059SGregory Neil Shapiro 	{ '=', MATCHCLASS },	{ '~', MATCHNCLASS },
10740266059SGregory Neil Shapiro 
10840266059SGregory Neil Shapiro 	/* these are RHS metasymbols */
10940266059SGregory Neil Shapiro 	{ '#', CANONNET },	{ '@', CANONHOST },	{ ':', CANONUSER },
11040266059SGregory Neil Shapiro 	{ '>', CALLSUBR },
11140266059SGregory Neil Shapiro 
11240266059SGregory Neil Shapiro 	/* the conditional operations */
11340266059SGregory Neil Shapiro 	{ '?', CONDIF },	{ '|', CONDELSE },	{ '.', CONDFI },
11440266059SGregory Neil Shapiro 
11540266059SGregory Neil Shapiro 	/* the hostname lookup characters */
11640266059SGregory Neil Shapiro 	{ '[', HOSTBEGIN },	{ ']', HOSTEND },
11740266059SGregory Neil Shapiro 	{ '(', LOOKUPBEGIN },	{ ')', LOOKUPEND },
11840266059SGregory Neil Shapiro 
11940266059SGregory Neil Shapiro 	/* miscellaneous control characters */
12040266059SGregory Neil Shapiro 	{ '&', MACRODEXPAND },
12140266059SGregory Neil Shapiro 
12240266059SGregory Neil Shapiro 	{ '\0', '\0' }
12340266059SGregory Neil Shapiro };
12440266059SGregory Neil Shapiro 
12540266059SGregory Neil Shapiro #define MACBINDING(name, mid) \
12640266059SGregory Neil Shapiro 		stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
12740266059SGregory Neil Shapiro 		MacroName[mid] = name;
12840266059SGregory Neil Shapiro 
12940266059SGregory Neil Shapiro void
initmacros(e)13040266059SGregory Neil Shapiro initmacros(e)
131d0cef73dSGregory Neil Shapiro 	ENVELOPE *e;
13240266059SGregory Neil Shapiro {
133d0cef73dSGregory Neil Shapiro 	struct metamac *m;
134d0cef73dSGregory Neil Shapiro 	int c;
13540266059SGregory Neil Shapiro 	char buf[5];
13640266059SGregory Neil Shapiro 
13740266059SGregory Neil Shapiro 	for (m = MetaMacros; m->metaname != '\0'; m++)
13840266059SGregory Neil Shapiro 	{
13940266059SGregory Neil Shapiro 		buf[0] = m->metaval;
14040266059SGregory Neil Shapiro 		buf[1] = '\0';
14140266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
14240266059SGregory Neil Shapiro 	}
14340266059SGregory Neil Shapiro 	buf[0] = MATCHREPL;
14440266059SGregory Neil Shapiro 	buf[2] = '\0';
14540266059SGregory Neil Shapiro 	for (c = '0'; c <= '9'; c++)
14640266059SGregory Neil Shapiro 	{
14740266059SGregory Neil Shapiro 		buf[1] = c;
14840266059SGregory Neil Shapiro 		macdefine(&e->e_macro, A_TEMP, c, buf);
14940266059SGregory Neil Shapiro 	}
15040266059SGregory Neil Shapiro 
15140266059SGregory Neil Shapiro 	/* set defaults for some macros sendmail will use later */
15240266059SGregory Neil Shapiro 	macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
15340266059SGregory Neil Shapiro 
15440266059SGregory Neil Shapiro 	/* set up external names for some internal macros */
15540266059SGregory Neil Shapiro 	MACBINDING("opMode", MID_OPMODE);
15640266059SGregory Neil Shapiro 	/*XXX should probably add equivalents for all short macros here XXX*/
15740266059SGregory Neil Shapiro }
158d0cef73dSGregory Neil Shapiro 
15940266059SGregory Neil Shapiro /*
160d0cef73dSGregory Neil Shapiro **  EXPAND/DOEXPAND -- macro expand a string using $x escapes.
1612fb4f839SGregory Neil Shapiro **	(including conditionals, e.g., $?x Y $| N $.)
162c2aa98e2SPeter Wemm **
163c2aa98e2SPeter Wemm **	Parameters:
1642fb4f839SGregory Neil Shapiro **		s -- the string to expand. [i]
1652fb4f839SGregory Neil Shapiro **		buf -- the place to put the expansion. [i]
166c2aa98e2SPeter Wemm **		bufsize -- the size of the buffer.
167d0cef73dSGregory Neil Shapiro **		explevel -- the depth of expansion (doexpand only)
168c2aa98e2SPeter Wemm **		e -- envelope in which to work.
169c2aa98e2SPeter Wemm **
170c2aa98e2SPeter Wemm **	Returns:
171c2aa98e2SPeter Wemm **		none.
172c2aa98e2SPeter Wemm */
173c2aa98e2SPeter Wemm 
174d0cef73dSGregory Neil Shapiro static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *));
175d0cef73dSGregory Neil Shapiro 
176d0cef73dSGregory Neil Shapiro static void
doexpand(s,buf,bufsize,explevel,e)177d0cef73dSGregory Neil Shapiro doexpand(s, buf, bufsize, explevel, e)
178d0cef73dSGregory Neil Shapiro 	char *s;
179d0cef73dSGregory Neil Shapiro 	char *buf;
180c2aa98e2SPeter Wemm 	size_t bufsize;
181d0cef73dSGregory Neil Shapiro 	int explevel;
182d0cef73dSGregory Neil Shapiro 	ENVELOPE *e;
183c2aa98e2SPeter Wemm {
184d0cef73dSGregory Neil Shapiro 	char *xp;
185d0cef73dSGregory Neil Shapiro 	char *q;
186c2aa98e2SPeter Wemm 	bool skipping;		/* set if conditionally skipping output */
18740266059SGregory Neil Shapiro 	bool recurse;		/* set if recursion required */
18840266059SGregory Neil Shapiro 	size_t i;
189c2aa98e2SPeter Wemm 	int skiplev;		/* skipping nesting level */
190c2aa98e2SPeter Wemm 	int iflev;		/* if nesting level */
191d0cef73dSGregory Neil Shapiro 	bool quotenext;		/* quote the following character */
192c2aa98e2SPeter Wemm 	char xbuf[MACBUFSIZE];
193c2aa98e2SPeter Wemm 
194c2aa98e2SPeter Wemm 	if (tTd(35, 24))
195c2aa98e2SPeter Wemm 	{
19640266059SGregory Neil Shapiro 		sm_dprintf("expand(");
197e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), s);
19840266059SGregory Neil Shapiro 		sm_dprintf(")\n");
199c2aa98e2SPeter Wemm 	}
200c2aa98e2SPeter Wemm 
20140266059SGregory Neil Shapiro 	recurse = false;
20240266059SGregory Neil Shapiro 	skipping = false;
203c2aa98e2SPeter Wemm 	skiplev = 0;
204c2aa98e2SPeter Wemm 	iflev = 0;
205d0cef73dSGregory Neil Shapiro 	quotenext = false;
206c2aa98e2SPeter Wemm 	if (s == NULL)
207c2aa98e2SPeter Wemm 		s = "";
208c2aa98e2SPeter Wemm 	for (xp = xbuf; *s != '\0'; s++)
209c2aa98e2SPeter Wemm 	{
210c2aa98e2SPeter Wemm 		int c;
211c2aa98e2SPeter Wemm 
212c2aa98e2SPeter Wemm 		/*
213c2aa98e2SPeter Wemm 		**  Check for non-ordinary (special?) character.
214c2aa98e2SPeter Wemm 		**	'q' will be the interpolated quantity.
215c2aa98e2SPeter Wemm 		*/
216c2aa98e2SPeter Wemm 
217c2aa98e2SPeter Wemm 		q = NULL;
218d0cef73dSGregory Neil Shapiro 		c = *s & 0377;
219d0cef73dSGregory Neil Shapiro 
220d0cef73dSGregory Neil Shapiro 		if (quotenext)
221d0cef73dSGregory Neil Shapiro 		{
222d0cef73dSGregory Neil Shapiro 			quotenext = false;
223d0cef73dSGregory Neil Shapiro 			goto simpleinterpolate;
224d0cef73dSGregory Neil Shapiro 		}
225d0cef73dSGregory Neil Shapiro 
226d0cef73dSGregory Neil Shapiro 		switch (c)
227c2aa98e2SPeter Wemm 		{
228c2aa98e2SPeter Wemm 		  case CONDIF:		/* see if var set */
229c2aa98e2SPeter Wemm 			iflev++;
230d0cef73dSGregory Neil Shapiro 			c = *++s & 0377;
231c2aa98e2SPeter Wemm 			if (skipping)
232c2aa98e2SPeter Wemm 				skiplev++;
233c2aa98e2SPeter Wemm 			else
23406f25ae9SGregory Neil Shapiro 			{
23506f25ae9SGregory Neil Shapiro 				char *mv;
23606f25ae9SGregory Neil Shapiro 
23706f25ae9SGregory Neil Shapiro 				mv = macvalue(c, e);
23806f25ae9SGregory Neil Shapiro 				skipping = (mv == NULL || *mv == '\0');
23906f25ae9SGregory Neil Shapiro 			}
240c2aa98e2SPeter Wemm 			continue;
241c2aa98e2SPeter Wemm 
242c2aa98e2SPeter Wemm 		  case CONDELSE:	/* change state of skipping */
243c2aa98e2SPeter Wemm 			if (iflev == 0)
24440266059SGregory Neil Shapiro 				break;	/* XXX: error */
245c2aa98e2SPeter Wemm 			if (skiplev == 0)
246c2aa98e2SPeter Wemm 				skipping = !skipping;
247c2aa98e2SPeter Wemm 			continue;
248c2aa98e2SPeter Wemm 
249c2aa98e2SPeter Wemm 		  case CONDFI:		/* stop skipping */
250c2aa98e2SPeter Wemm 			if (iflev == 0)
25140266059SGregory Neil Shapiro 				break;	/* XXX: error */
252c2aa98e2SPeter Wemm 			iflev--;
253c2aa98e2SPeter Wemm 			if (skiplev == 0)
25440266059SGregory Neil Shapiro 				skipping = false;
255c2aa98e2SPeter Wemm 			if (skipping)
256c2aa98e2SPeter Wemm 				skiplev--;
257c2aa98e2SPeter Wemm 			continue;
258c2aa98e2SPeter Wemm 
259c2aa98e2SPeter Wemm 		  case MACROEXPAND:	/* macro interpolation */
260193538b7SGregory Neil Shapiro 			c = bitidx(*++s);
261c2aa98e2SPeter Wemm 			if (c != '\0')
262c2aa98e2SPeter Wemm 				q = macvalue(c, e);
263c2aa98e2SPeter Wemm 			else
264c2aa98e2SPeter Wemm 			{
265c2aa98e2SPeter Wemm 				s--;
266c2aa98e2SPeter Wemm 				q = NULL;
267c2aa98e2SPeter Wemm 			}
268c2aa98e2SPeter Wemm 			if (q == NULL)
269c2aa98e2SPeter Wemm 				continue;
270c2aa98e2SPeter Wemm 			break;
271d0cef73dSGregory Neil Shapiro 
272d0cef73dSGregory Neil Shapiro 		  case METAQUOTE:
273d0cef73dSGregory Neil Shapiro 			/* next octet completely quoted */
274d0cef73dSGregory Neil Shapiro 			quotenext = true;
275d0cef73dSGregory Neil Shapiro 			break;
276c2aa98e2SPeter Wemm 		}
277c2aa98e2SPeter Wemm 
278c2aa98e2SPeter Wemm 		/*
279c2aa98e2SPeter Wemm 		**  Interpolate q or output one character
280c2aa98e2SPeter Wemm 		*/
281c2aa98e2SPeter Wemm 
282d0cef73dSGregory Neil Shapiro   simpleinterpolate:
283d0cef73dSGregory Neil Shapiro 		if (skipping || xp >= &xbuf[sizeof(xbuf) - 1])
284c2aa98e2SPeter Wemm 			continue;
285c2aa98e2SPeter Wemm 		if (q == NULL)
286c2aa98e2SPeter Wemm 			*xp++ = c;
287c2aa98e2SPeter Wemm 		else
288c2aa98e2SPeter Wemm 		{
289c2aa98e2SPeter Wemm 			/* copy to end of q or max space remaining in buf */
290d0cef73dSGregory Neil Shapiro 			bool hiderecurse = false;
291d0cef73dSGregory Neil Shapiro 
292d0cef73dSGregory Neil Shapiro 			while ((c = *q++) != '\0' &&
293d0cef73dSGregory Neil Shapiro 				xp < &xbuf[sizeof(xbuf) - 1])
294c2aa98e2SPeter Wemm 			{
295c2aa98e2SPeter Wemm 				/* check for any sendmail metacharacters */
296d0cef73dSGregory Neil Shapiro 				if (!hiderecurse && (c & 0340) == 0200)
29740266059SGregory Neil Shapiro 					recurse = true;
298c2aa98e2SPeter Wemm 				*xp++ = c;
299d0cef73dSGregory Neil Shapiro 
300d0cef73dSGregory Neil Shapiro 				/* give quoted characters a free ride */
301d0cef73dSGregory Neil Shapiro 				hiderecurse = (c & 0377) == METAQUOTE;
302c2aa98e2SPeter Wemm 			}
303c2aa98e2SPeter Wemm 		}
304c2aa98e2SPeter Wemm 	}
305c2aa98e2SPeter Wemm 	*xp = '\0';
306c2aa98e2SPeter Wemm 
307d0cef73dSGregory Neil Shapiro 	if (tTd(35, 28))
308c2aa98e2SPeter Wemm 	{
309d0cef73dSGregory Neil Shapiro 		sm_dprintf("expand(%d) ==> ", explevel);
310e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), xbuf);
31140266059SGregory Neil Shapiro 		sm_dprintf("\n");
312c2aa98e2SPeter Wemm 	}
313c2aa98e2SPeter Wemm 
314c2aa98e2SPeter Wemm 	/* recurse as appropriate */
315c2aa98e2SPeter Wemm 	if (recurse)
316c2aa98e2SPeter Wemm 	{
317c2aa98e2SPeter Wemm 		if (explevel < MaxMacroRecursion)
318c2aa98e2SPeter Wemm 		{
319d0cef73dSGregory Neil Shapiro 			doexpand(xbuf, buf, bufsize, explevel + 1, e);
320c2aa98e2SPeter Wemm 			return;
321c2aa98e2SPeter Wemm 		}
322c2aa98e2SPeter Wemm 		syserr("expand: recursion too deep (%d max)",
323c2aa98e2SPeter Wemm 			MaxMacroRecursion);
324c2aa98e2SPeter Wemm 	}
325c2aa98e2SPeter Wemm 
326c2aa98e2SPeter Wemm 	/* copy results out */
327d0cef73dSGregory Neil Shapiro 	if (explevel == 0)
328d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpy(buf, xbuf, bufsize);
329d0cef73dSGregory Neil Shapiro 	else
330d0cef73dSGregory Neil Shapiro 	{
331d0cef73dSGregory Neil Shapiro 		/* leave in internal form */
332c2aa98e2SPeter Wemm 		i = xp - xbuf;
33340266059SGregory Neil Shapiro 		if (i >= bufsize)
334c2aa98e2SPeter Wemm 			i = bufsize - 1;
33506f25ae9SGregory Neil Shapiro 		memmove(buf, xbuf, i);
336c2aa98e2SPeter Wemm 		buf[i] = '\0';
337c2aa98e2SPeter Wemm 	}
33840266059SGregory Neil Shapiro 
339d0cef73dSGregory Neil Shapiro 	if (tTd(35, 24))
340d0cef73dSGregory Neil Shapiro 	{
341d0cef73dSGregory Neil Shapiro 		sm_dprintf("expand ==> ");
342d0cef73dSGregory Neil Shapiro 		xputs(sm_debug_file(), buf);
343d0cef73dSGregory Neil Shapiro 		sm_dprintf("\n");
344d0cef73dSGregory Neil Shapiro 	}
345d0cef73dSGregory Neil Shapiro }
346d0cef73dSGregory Neil Shapiro 
347d0cef73dSGregory Neil Shapiro void
expand(s,buf,bufsize,e)348d0cef73dSGregory Neil Shapiro expand(s, buf, bufsize, e)
349d0cef73dSGregory Neil Shapiro 	char *s;
350d0cef73dSGregory Neil Shapiro 	char *buf;
351d0cef73dSGregory Neil Shapiro 	size_t bufsize;
352d0cef73dSGregory Neil Shapiro 	ENVELOPE *e;
353d0cef73dSGregory Neil Shapiro {
354d0cef73dSGregory Neil Shapiro 	doexpand(s, buf, bufsize, 0, e);
355d0cef73dSGregory Neil Shapiro }
356d0cef73dSGregory Neil Shapiro 
35740266059SGregory Neil Shapiro /*
3585b0945b5SGregory Neil Shapiro **  MACTABCLEAR -- clear entire macro table
3595b0945b5SGregory Neil Shapiro **
3605b0945b5SGregory Neil Shapiro **	Parameters:
3615b0945b5SGregory Neil Shapiro **		mac -- Macro table.
3625b0945b5SGregory Neil Shapiro **
3635b0945b5SGregory Neil Shapiro **	Returns:
3645b0945b5SGregory Neil Shapiro **		none.
3655b0945b5SGregory Neil Shapiro **
3665b0945b5SGregory Neil Shapiro **	Side Effects:
3675b0945b5SGregory Neil Shapiro **		clears entire mac structure including rpool pointer!
3685b0945b5SGregory Neil Shapiro */
3695b0945b5SGregory Neil Shapiro 
3705b0945b5SGregory Neil Shapiro void
mactabclear(mac)3715b0945b5SGregory Neil Shapiro mactabclear(mac)
3725b0945b5SGregory Neil Shapiro 	MACROS_T *mac;
3735b0945b5SGregory Neil Shapiro {
3745b0945b5SGregory Neil Shapiro 	int i;
3755b0945b5SGregory Neil Shapiro 
3765b0945b5SGregory Neil Shapiro 	if (mac->mac_rpool == NULL)
3775b0945b5SGregory Neil Shapiro 	{
3785b0945b5SGregory Neil Shapiro 		for (i = 0; i < MAXMACROID; i++)
3795b0945b5SGregory Neil Shapiro 			SM_FREE(mac->mac_table[i]);
3805b0945b5SGregory Neil Shapiro 	}
3815b0945b5SGregory Neil Shapiro 	memset((char *) mac, '\0', sizeof(*mac));
3825b0945b5SGregory Neil Shapiro }
3835b0945b5SGregory Neil Shapiro 
3845b0945b5SGregory Neil Shapiro /*
38540266059SGregory Neil Shapiro **  MACDEFINE -- bind a macro name to a value
386c2aa98e2SPeter Wemm **
38740266059SGregory Neil Shapiro **	Set a macro to a value, with fancy storage management.
38840266059SGregory Neil Shapiro **	macdefine will make a copy of the value, if required,
38940266059SGregory Neil Shapiro **	and will ensure that the storage for the previous value
39040266059SGregory Neil Shapiro **	is not leaked.
391c2aa98e2SPeter Wemm **
392c2aa98e2SPeter Wemm **	Parameters:
39340266059SGregory Neil Shapiro **		mac -- Macro table.
39440266059SGregory Neil Shapiro **		vclass -- storage class of 'value', ignored if value==NULL.
39540266059SGregory Neil Shapiro **			A_HEAP	means that the value was allocated by
39640266059SGregory Neil Shapiro **				malloc, and that macdefine owns the storage.
39740266059SGregory Neil Shapiro **			A_TEMP	means that value points to temporary storage,
39840266059SGregory Neil Shapiro **				and thus macdefine needs to make a copy.
39940266059SGregory Neil Shapiro **			A_PERM	means that value points to storage that
40040266059SGregory Neil Shapiro **				will remain allocated and unchanged for
40140266059SGregory Neil Shapiro **				at least the lifetime of mac.  Use A_PERM if:
40240266059SGregory Neil Shapiro **				-- value == NULL,
40340266059SGregory Neil Shapiro **				-- value points to a string literal,
40440266059SGregory Neil Shapiro **				-- value was allocated from mac->mac_rpool
40540266059SGregory Neil Shapiro **				   or (in the case of an envelope macro)
40640266059SGregory Neil Shapiro **				   from e->e_rpool,
40740266059SGregory Neil Shapiro **				-- in the case of an envelope macro,
40840266059SGregory Neil Shapiro **				   value is a string member of the envelope
40940266059SGregory Neil Shapiro **				   such as e->e_sender.
41040266059SGregory Neil Shapiro **		id -- Macro id.  This is a single character macro name
41140266059SGregory Neil Shapiro **			such as 'g', or a value returned by macid().
41240266059SGregory Neil Shapiro **		value -- Macro value: either NULL, or a string.
413d39bd2c1SGregory Neil Shapiro **
414d39bd2c1SGregory Neil Shapiro **	Returns:
415d39bd2c1SGregory Neil Shapiro **		none.
416c2aa98e2SPeter Wemm */
417c2aa98e2SPeter Wemm 
418c2aa98e2SPeter Wemm void
41940266059SGregory Neil Shapiro #if SM_HEAP_CHECK
macdefine_tagged(mac,vclass,id,value,file,line,grp)42040266059SGregory Neil Shapiro macdefine_tagged(mac, vclass, id, value, file, line, grp)
4212fb4f839SGregory Neil Shapiro #else
42240266059SGregory Neil Shapiro macdefine(mac, vclass, id, value)
4232fb4f839SGregory Neil Shapiro #endif
42440266059SGregory Neil Shapiro 	MACROS_T *mac;
42540266059SGregory Neil Shapiro 	ARGCLASS_T vclass;
42640266059SGregory Neil Shapiro 	int id;
42740266059SGregory Neil Shapiro 	char *value;
42840266059SGregory Neil Shapiro #if SM_HEAP_CHECK
42940266059SGregory Neil Shapiro 	char *file;
43040266059SGregory Neil Shapiro 	int line;
43140266059SGregory Neil Shapiro 	int grp;
4322fb4f839SGregory Neil Shapiro #endif
433c2aa98e2SPeter Wemm {
43440266059SGregory Neil Shapiro 	char *newvalue;
43506f25ae9SGregory Neil Shapiro 
43640266059SGregory Neil Shapiro 	if (id < 0 || id > MAXMACROID)
43740266059SGregory Neil Shapiro 		return;
43840266059SGregory Neil Shapiro 
439c2aa98e2SPeter Wemm 	if (tTd(35, 9))
440c2aa98e2SPeter Wemm 	{
44140266059SGregory Neil Shapiro 		sm_dprintf("%sdefine(%s as ",
44240266059SGregory Neil Shapiro 			mac->mac_table[id] == NULL ? "" : "re", macname(id));
443e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), value);
44440266059SGregory Neil Shapiro 		sm_dprintf(")\n");
445c2aa98e2SPeter Wemm 	}
4462fb4f839SGregory Neil Shapiro #if USE_EAI && 0
447d39bd2c1SGregory Neil Shapiro //	if (('j' == id || 'm' == id) && !addr_is_ascii(value))
448d39bd2c1SGregory Neil Shapiro //		return an error/warning to caller and let them handle it.
4492fb4f839SGregory Neil Shapiro #endif
45040266059SGregory Neil Shapiro 
45140266059SGregory Neil Shapiro 	if (mac->mac_rpool == NULL)
45240266059SGregory Neil Shapiro 	{
45340266059SGregory Neil Shapiro 		char *freeit = NULL;
45440266059SGregory Neil Shapiro 
45540266059SGregory Neil Shapiro 		if (mac->mac_table[id] != NULL &&
45640266059SGregory Neil Shapiro 		    bitnset(id, mac->mac_allocated))
45740266059SGregory Neil Shapiro 			freeit = mac->mac_table[id];
45840266059SGregory Neil Shapiro 
45940266059SGregory Neil Shapiro 		if (value == NULL || vclass == A_HEAP)
46040266059SGregory Neil Shapiro 		{
46140266059SGregory Neil Shapiro 			sm_heap_checkptr_tagged(value, file, line);
46240266059SGregory Neil Shapiro 			newvalue = value;
46340266059SGregory Neil Shapiro 			clrbitn(id, mac->mac_allocated);
46440266059SGregory Neil Shapiro 		}
46540266059SGregory Neil Shapiro 		else
46640266059SGregory Neil Shapiro 		{
467e92d3f3fSGregory Neil Shapiro #if SM_HEAP_CHECK
46840266059SGregory Neil Shapiro 			newvalue = sm_strdup_tagged_x(value, file, line, 0);
4695b0945b5SGregory Neil Shapiro #else
470e92d3f3fSGregory Neil Shapiro 			newvalue = sm_strdup_x(value);
4715b0945b5SGregory Neil Shapiro #endif
47240266059SGregory Neil Shapiro 			setbitn(id, mac->mac_allocated);
47340266059SGregory Neil Shapiro 		}
47440266059SGregory Neil Shapiro 		mac->mac_table[id] = newvalue;
47540266059SGregory Neil Shapiro 		if (freeit != NULL)
47640266059SGregory Neil Shapiro 			sm_free(freeit);
47740266059SGregory Neil Shapiro 	}
47840266059SGregory Neil Shapiro 	else
47940266059SGregory Neil Shapiro 	{
48040266059SGregory Neil Shapiro 		if (value == NULL || vclass == A_PERM)
48140266059SGregory Neil Shapiro 			newvalue = value;
48240266059SGregory Neil Shapiro 		else
48340266059SGregory Neil Shapiro 			newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
48440266059SGregory Neil Shapiro 		mac->mac_table[id] = newvalue;
48540266059SGregory Neil Shapiro 		if (vclass == A_HEAP)
48640266059SGregory Neil Shapiro 			sm_free(value);
48740266059SGregory Neil Shapiro 	}
48806f25ae9SGregory Neil Shapiro 
48906f25ae9SGregory Neil Shapiro #if _FFR_RESET_MACRO_GLOBALS
49040266059SGregory Neil Shapiro 	switch (id)
49106f25ae9SGregory Neil Shapiro 	{
49206f25ae9SGregory Neil Shapiro 	  case 'j':
49340266059SGregory Neil Shapiro 		PSTRSET(MyHostName, value);
49406f25ae9SGregory Neil Shapiro 		break;
49506f25ae9SGregory Neil Shapiro 	}
49606f25ae9SGregory Neil Shapiro #endif /* _FFR_RESET_MACRO_GLOBALS */
497c2aa98e2SPeter Wemm }
49840266059SGregory Neil Shapiro 
49940266059SGregory Neil Shapiro /*
50040266059SGregory Neil Shapiro **  MACSET -- set a named macro to a value (low level)
50140266059SGregory Neil Shapiro **
50240266059SGregory Neil Shapiro **	No fancy storage management; the caller takes full responsibility.
50340266059SGregory Neil Shapiro **	Often used with macget; see also macdefine.
50440266059SGregory Neil Shapiro **
50540266059SGregory Neil Shapiro **	Parameters:
50640266059SGregory Neil Shapiro **		mac -- Macro table.
50740266059SGregory Neil Shapiro **		i -- Macro name, specified as an integer offset.
50840266059SGregory Neil Shapiro **		value -- Macro value: either NULL, or a string.
509d39bd2c1SGregory Neil Shapiro **
510d39bd2c1SGregory Neil Shapiro **	Returns:
511d39bd2c1SGregory Neil Shapiro **		none.
51240266059SGregory Neil Shapiro */
51340266059SGregory Neil Shapiro 
51440266059SGregory Neil Shapiro void
macset(mac,i,value)51540266059SGregory Neil Shapiro macset(mac, i, value)
51640266059SGregory Neil Shapiro 	MACROS_T *mac;
51740266059SGregory Neil Shapiro 	int i;
51840266059SGregory Neil Shapiro 	char *value;
51940266059SGregory Neil Shapiro {
52040266059SGregory Neil Shapiro 	if (i < 0 || i > MAXMACROID)
52140266059SGregory Neil Shapiro 		return;
52240266059SGregory Neil Shapiro 
52340266059SGregory Neil Shapiro 	if (tTd(35, 9))
52440266059SGregory Neil Shapiro 	{
52540266059SGregory Neil Shapiro 		sm_dprintf("macset(%s as ", macname(i));
526e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), value);
52740266059SGregory Neil Shapiro 		sm_dprintf(")\n");
52840266059SGregory Neil Shapiro 	}
52940266059SGregory Neil Shapiro 	mac->mac_table[i] = value;
53040266059SGregory Neil Shapiro }
53140266059SGregory Neil Shapiro 
53240266059SGregory Neil Shapiro /*
533c2aa98e2SPeter Wemm **  MACVALUE -- return uninterpreted value of a macro.
534c2aa98e2SPeter Wemm **
53540266059SGregory Neil Shapiro **	Does fancy path searching.
53640266059SGregory Neil Shapiro **	The low level counterpart is macget.
53740266059SGregory Neil Shapiro **
538c2aa98e2SPeter Wemm **	Parameters:
539c2aa98e2SPeter Wemm **		n -- the name of the macro.
54040266059SGregory Neil Shapiro **		e -- envelope in which to start looking for the macro.
541c2aa98e2SPeter Wemm **
542c2aa98e2SPeter Wemm **	Returns:
543c2aa98e2SPeter Wemm **		The value of n.
544c2aa98e2SPeter Wemm **
545c2aa98e2SPeter Wemm **	Side Effects:
546c2aa98e2SPeter Wemm **		none.
547c2aa98e2SPeter Wemm */
548c2aa98e2SPeter Wemm 
549c2aa98e2SPeter Wemm char *
macvalue(n,e)550c2aa98e2SPeter Wemm macvalue(n, e)
551c2aa98e2SPeter Wemm 	int n;
552d0cef73dSGregory Neil Shapiro 	ENVELOPE *e;
553c2aa98e2SPeter Wemm {
554193538b7SGregory Neil Shapiro 	n = bitidx(n);
55540266059SGregory Neil Shapiro 	if (e != NULL && e->e_mci != NULL)
55640266059SGregory Neil Shapiro 	{
557d0cef73dSGregory Neil Shapiro 		char *p = e->e_mci->mci_macro.mac_table[n];
55840266059SGregory Neil Shapiro 
55940266059SGregory Neil Shapiro 		if (p != NULL)
56040266059SGregory Neil Shapiro 			return p;
56140266059SGregory Neil Shapiro 	}
562c2aa98e2SPeter Wemm 	while (e != NULL)
563c2aa98e2SPeter Wemm 	{
564d0cef73dSGregory Neil Shapiro 		char *p = e->e_macro.mac_table[n];
565c2aa98e2SPeter Wemm 
566c2aa98e2SPeter Wemm 		if (p != NULL)
56706f25ae9SGregory Neil Shapiro 			return p;
568602a2b1bSGregory Neil Shapiro 		if (e == e->e_parent)
569602a2b1bSGregory Neil Shapiro 			break;
570c2aa98e2SPeter Wemm 		e = e->e_parent;
571c2aa98e2SPeter Wemm 	}
5725b0945b5SGregory Neil Shapiro #if _FFR_BLANKENV_MACV
5735b0945b5SGregory Neil Shapiro 	if (LOOKUP_MACRO_IN_BLANKENV && e != &BlankEnvelope)
5745b0945b5SGregory Neil Shapiro 	{
5755b0945b5SGregory Neil Shapiro 		char *p = BlankEnvelope.e_macro.mac_table[n];
5765b0945b5SGregory Neil Shapiro 
5775b0945b5SGregory Neil Shapiro 		if (p != NULL)
5785b0945b5SGregory Neil Shapiro 			return p;
5795b0945b5SGregory Neil Shapiro 	}
5805b0945b5SGregory Neil Shapiro #endif
58140266059SGregory Neil Shapiro 	return GlobalMacros.mac_table[n];
582c2aa98e2SPeter Wemm }
583d0cef73dSGregory Neil Shapiro 
58440266059SGregory Neil Shapiro /*
585c2aa98e2SPeter Wemm **  MACNAME -- return the name of a macro given its internal id
586c2aa98e2SPeter Wemm **
587c2aa98e2SPeter Wemm **	Parameter:
588c2aa98e2SPeter Wemm **		n -- the id of the macro
589c2aa98e2SPeter Wemm **
590c2aa98e2SPeter Wemm **	Returns:
591c2aa98e2SPeter Wemm **		The name of n.
592c2aa98e2SPeter Wemm **
593c2aa98e2SPeter Wemm **	Side Effects:
594c2aa98e2SPeter Wemm **		none.
595d0cef73dSGregory Neil Shapiro **
596d0cef73dSGregory Neil Shapiro **	WARNING:
597d0cef73dSGregory Neil Shapiro **		Not thread-safe.
598c2aa98e2SPeter Wemm */
599c2aa98e2SPeter Wemm 
600c2aa98e2SPeter Wemm char *
macname(n)601c2aa98e2SPeter Wemm macname(n)
602c2aa98e2SPeter Wemm 	int n;
603c2aa98e2SPeter Wemm {
604c2aa98e2SPeter Wemm 	static char mbuf[2];
605c2aa98e2SPeter Wemm 
606d0cef73dSGregory Neil Shapiro 	n = (int)(unsigned char)n;
607d0cef73dSGregory Neil Shapiro 	if (n > MAXMACROID)
608d0cef73dSGregory Neil Shapiro 		return "***OUT OF RANGE MACRO***";
609d0cef73dSGregory Neil Shapiro 
610d0cef73dSGregory Neil Shapiro 	/* if not ASCII printable, look up the name */
611d0cef73dSGregory Neil Shapiro 	if (n <= 0x20 || n > 0x7f)
612c2aa98e2SPeter Wemm 	{
613c2aa98e2SPeter Wemm 		char *p = MacroName[n];
614c2aa98e2SPeter Wemm 
615c2aa98e2SPeter Wemm 		if (p != NULL)
616c2aa98e2SPeter Wemm 			return p;
617c2aa98e2SPeter Wemm 		return "***UNDEFINED MACRO***";
618c2aa98e2SPeter Wemm 	}
619d0cef73dSGregory Neil Shapiro 
620d0cef73dSGregory Neil Shapiro 	/* if in the ASCII graphic range, just return the id directly */
621c2aa98e2SPeter Wemm 	mbuf[0] = n;
622c2aa98e2SPeter Wemm 	mbuf[1] = '\0';
623c2aa98e2SPeter Wemm 	return mbuf;
624c2aa98e2SPeter Wemm }
625d0cef73dSGregory Neil Shapiro 
62640266059SGregory Neil Shapiro /*
62740266059SGregory Neil Shapiro **  MACID_PARSE -- return id of macro identified by its name
628c2aa98e2SPeter Wemm **
629c2aa98e2SPeter Wemm **	Parameters:
630c2aa98e2SPeter Wemm **		p -- pointer to name string -- either a single
631c2aa98e2SPeter Wemm **			character or {name}.
632c2aa98e2SPeter Wemm **		ep -- filled in with the pointer to the byte
633c2aa98e2SPeter Wemm **			after the name.
634c2aa98e2SPeter Wemm **
635c2aa98e2SPeter Wemm **	Returns:
63640266059SGregory Neil Shapiro **		0 -- An error was detected.
637d0cef73dSGregory Neil Shapiro **		1..MAXMACROID -- The internal id code for this macro.
638c2aa98e2SPeter Wemm **
639c2aa98e2SPeter Wemm **	Side Effects:
640c2aa98e2SPeter Wemm **		If this is a new macro name, a new id is allocated.
64140266059SGregory Neil Shapiro **		On error, syserr is called.
642c2aa98e2SPeter Wemm */
643c2aa98e2SPeter Wemm 
644c2aa98e2SPeter Wemm int
macid_parse(p,ep)64540266059SGregory Neil Shapiro macid_parse(p, ep)
646d0cef73dSGregory Neil Shapiro 	char *p;
647c2aa98e2SPeter Wemm 	char **ep;
648c2aa98e2SPeter Wemm {
649c2aa98e2SPeter Wemm 	int mid;
650d0cef73dSGregory Neil Shapiro 	char *bp;
651065a643dSPeter Wemm 	char mbuf[MAXMACNAMELEN + 1];
652c2aa98e2SPeter Wemm 
653c2aa98e2SPeter Wemm 	if (tTd(35, 14))
654c2aa98e2SPeter Wemm 	{
65540266059SGregory Neil Shapiro 		sm_dprintf("macid(");
656e92d3f3fSGregory Neil Shapiro 		xputs(sm_debug_file(), p);
65740266059SGregory Neil Shapiro 		sm_dprintf(") => ");
658c2aa98e2SPeter Wemm 	}
659c2aa98e2SPeter Wemm 
660c2aa98e2SPeter Wemm 	if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
661c2aa98e2SPeter Wemm 	{
662c2aa98e2SPeter Wemm 		syserr("Name required for macro/class");
663c2aa98e2SPeter Wemm 		if (ep != NULL)
664c2aa98e2SPeter Wemm 			*ep = p;
665c2aa98e2SPeter Wemm 		if (tTd(35, 14))
66640266059SGregory Neil Shapiro 			sm_dprintf("NULL\n");
667193538b7SGregory Neil Shapiro 		return 0;
668c2aa98e2SPeter Wemm 	}
669c2aa98e2SPeter Wemm 	if (*p != '{')
670c2aa98e2SPeter Wemm 	{
671c2aa98e2SPeter Wemm 		/* the macro is its own code */
672c2aa98e2SPeter Wemm 		if (ep != NULL)
673c2aa98e2SPeter Wemm 			*ep = p + 1;
674c2aa98e2SPeter Wemm 		if (tTd(35, 14))
675d0cef73dSGregory Neil Shapiro 		{
676d0cef73dSGregory Neil Shapiro 			char buf[2];
677d0cef73dSGregory Neil Shapiro 
678d0cef73dSGregory Neil Shapiro 			buf[0] = *p;
679d0cef73dSGregory Neil Shapiro 			buf[1] = '\0';
680d0cef73dSGregory Neil Shapiro 			xputs(sm_debug_file(), buf);
681d0cef73dSGregory Neil Shapiro 			sm_dprintf("\n");
682d0cef73dSGregory Neil Shapiro 		}
683193538b7SGregory Neil Shapiro 		return bitidx(*p);
684c2aa98e2SPeter Wemm 	}
685c2aa98e2SPeter Wemm 	bp = mbuf;
686d0cef73dSGregory Neil Shapiro 	while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
687c2aa98e2SPeter Wemm 	{
688c2aa98e2SPeter Wemm 		if (isascii(*p) && (isalnum(*p) || *p == '_'))
689c2aa98e2SPeter Wemm 			*bp++ = *p;
690c2aa98e2SPeter Wemm 		else
691c2aa98e2SPeter Wemm 			syserr("Invalid macro/class character %c", *p);
692c2aa98e2SPeter Wemm 	}
693c2aa98e2SPeter Wemm 	*bp = '\0';
694c2aa98e2SPeter Wemm 	mid = -1;
695c2aa98e2SPeter Wemm 	if (*p == '\0')
696c2aa98e2SPeter Wemm 	{
697c2aa98e2SPeter Wemm 		syserr("Unbalanced { on %s", mbuf);	/* missing } */
698c2aa98e2SPeter Wemm 	}
699c2aa98e2SPeter Wemm 	else if (*p != '}')
700c2aa98e2SPeter Wemm 	{
701c2aa98e2SPeter Wemm 		syserr("Macro/class name ({%s}) too long (%d chars max)",
702d0cef73dSGregory Neil Shapiro 			mbuf, (int) (sizeof(mbuf) - 1));
703c2aa98e2SPeter Wemm 	}
704ffb83623SGregory Neil Shapiro 	else if (mbuf[1] == '\0' && mbuf[0] >= 0x20)
705c2aa98e2SPeter Wemm 	{
706c2aa98e2SPeter Wemm 		/* ${x} == $x */
707193538b7SGregory Neil Shapiro 		mid = bitidx(mbuf[0]);
708c2aa98e2SPeter Wemm 		p++;
709c2aa98e2SPeter Wemm 	}
710c2aa98e2SPeter Wemm 	else
711c2aa98e2SPeter Wemm 	{
712d0cef73dSGregory Neil Shapiro 		STAB *s;
713c2aa98e2SPeter Wemm 
714c2aa98e2SPeter Wemm 		s = stab(mbuf, ST_MACRO, ST_ENTER);
715c2aa98e2SPeter Wemm 		if (s->s_macro != 0)
716c2aa98e2SPeter Wemm 			mid = s->s_macro;
717c2aa98e2SPeter Wemm 		else
718c2aa98e2SPeter Wemm 		{
71906f25ae9SGregory Neil Shapiro 			if (NextMacroId > MAXMACROID)
720c2aa98e2SPeter Wemm 			{
72140266059SGregory Neil Shapiro 				syserr("Macro/class {%s}: too many long names",
72240266059SGregory Neil Shapiro 					mbuf);
723c2aa98e2SPeter Wemm 				s->s_macro = -1;
724c2aa98e2SPeter Wemm 			}
725c2aa98e2SPeter Wemm 			else
726c2aa98e2SPeter Wemm 			{
727c2aa98e2SPeter Wemm 				MacroName[NextMacroId] = s->s_name;
728ffb83623SGregory Neil Shapiro 				s->s_macro = mid = NextMacroId;
729ffb83623SGregory Neil Shapiro 				NextMacroId = NEXTMACROID(NextMacroId);
730c2aa98e2SPeter Wemm 			}
731c2aa98e2SPeter Wemm 		}
732c2aa98e2SPeter Wemm 		p++;
733c2aa98e2SPeter Wemm 	}
734c2aa98e2SPeter Wemm 	if (ep != NULL)
735c2aa98e2SPeter Wemm 		*ep = p;
736193538b7SGregory Neil Shapiro 	if (mid < 0 || mid > MAXMACROID)
737193538b7SGregory Neil Shapiro 	{
738193538b7SGregory Neil Shapiro 		syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
739193538b7SGregory Neil Shapiro 		if (tTd(35, 14))
74040266059SGregory Neil Shapiro 			sm_dprintf("NULL\n");
741193538b7SGregory Neil Shapiro 		return 0;
742193538b7SGregory Neil Shapiro 	}
743c2aa98e2SPeter Wemm 	if (tTd(35, 14))
74440266059SGregory Neil Shapiro 		sm_dprintf("0x%x\n", mid);
745c2aa98e2SPeter Wemm 	return mid;
746c2aa98e2SPeter Wemm }
747d0cef73dSGregory Neil Shapiro 
74840266059SGregory Neil Shapiro /*
749c2aa98e2SPeter Wemm **  WORDINCLASS -- tell if a word is in a specific class
750c2aa98e2SPeter Wemm **
751c2aa98e2SPeter Wemm **	Parameters:
752c2aa98e2SPeter Wemm **		str -- the name of the word to look up.
753c2aa98e2SPeter Wemm **		cl -- the class name.
754c2aa98e2SPeter Wemm **
755c2aa98e2SPeter Wemm **	Returns:
75640266059SGregory Neil Shapiro **		true if str can be found in cl.
75740266059SGregory Neil Shapiro **		false otherwise.
758c2aa98e2SPeter Wemm */
759c2aa98e2SPeter Wemm 
760c2aa98e2SPeter Wemm bool
wordinclass(str,cl)761c2aa98e2SPeter Wemm wordinclass(str, cl)
762c2aa98e2SPeter Wemm 	char *str;
763c2aa98e2SPeter Wemm 	int cl;
764c2aa98e2SPeter Wemm {
765d0cef73dSGregory Neil Shapiro 	STAB *s;
766d39bd2c1SGregory Neil Shapiro #if _FFR_DYN_CLASS
767d39bd2c1SGregory Neil Shapiro 	MAP *map;
768d39bd2c1SGregory Neil Shapiro 	int status;
769d39bd2c1SGregory Neil Shapiro 	char *p;
770d39bd2c1SGregory Neil Shapiro 	char key[MAXLINE];
771c2aa98e2SPeter Wemm 
772d39bd2c1SGregory Neil Shapiro 	p = macname(cl);
773d39bd2c1SGregory Neil Shapiro 	s = stab(p, ST_DYNMAP, ST_FIND);
774d39bd2c1SGregory Neil Shapiro 	if (NULL == s)
775d39bd2c1SGregory Neil Shapiro 	{
776d39bd2c1SGregory Neil Shapiro #endif
777c2aa98e2SPeter Wemm 		s = stab(str, ST_CLASS, ST_FIND);
778193538b7SGregory Neil Shapiro 		return s != NULL && bitnset(bitidx(cl), s->s_class);
779d39bd2c1SGregory Neil Shapiro #if _FFR_DYN_CLASS
780d39bd2c1SGregory Neil Shapiro 	}
781d39bd2c1SGregory Neil Shapiro 	map = &s->s_dynclass;
782d39bd2c1SGregory Neil Shapiro 	SM_REQUIRE(NULL != map);
783d39bd2c1SGregory Neil Shapiro 	SM_REQUIRE(!SM_IS_EMPTY(str));
784d39bd2c1SGregory Neil Shapiro 	if (bitset(MF_OPENBOGUS, map->map_mflags))
785d39bd2c1SGregory Neil Shapiro 	{
786d39bd2c1SGregory Neil Shapiro 		/* need to set some error! */
787d39bd2c1SGregory Neil Shapiro 		return false;
788d39bd2c1SGregory Neil Shapiro 	}
789d39bd2c1SGregory Neil Shapiro 
790d39bd2c1SGregory Neil Shapiro 	key[0] = '\0';
791d39bd2c1SGregory Neil Shapiro 	if (!SM_IS_EMPTY(map->map_tag))
792d39bd2c1SGregory Neil Shapiro 	{
793d39bd2c1SGregory Neil Shapiro 		sm_strlcpy(key, map->map_tag, sizeof(key));
794d39bd2c1SGregory Neil Shapiro 		sm_strlcat(key, ":", sizeof(key));
795d39bd2c1SGregory Neil Shapiro 	}
796d39bd2c1SGregory Neil Shapiro 	sm_strlcat(key, str, sizeof(key));
797d39bd2c1SGregory Neil Shapiro 	status = EX_OK;
798d39bd2c1SGregory Neil Shapiro 	p = (map->map_class->map_lookup)(map, key, NULL, &status);
799d39bd2c1SGregory Neil Shapiro 	if (NULL != p)
800d39bd2c1SGregory Neil Shapiro 		return true;
801d39bd2c1SGregory Neil Shapiro 	if ((EX_OK == status && NULL == p) || EX_NOTFOUND == status)
802d39bd2c1SGregory Neil Shapiro 		return false;
803d39bd2c1SGregory Neil Shapiro 
804d39bd2c1SGregory Neil Shapiro 	sm_syslog(LOG_WARNING, CurEnv->e_id,
805d39bd2c1SGregory Neil Shapiro 		"dynamic class: A{%s}: map lookup failed: key=%s, status=%d",
806d39bd2c1SGregory Neil Shapiro 		map->map_mname, key, status);
807d39bd2c1SGregory Neil Shapiro 
808d39bd2c1SGregory Neil Shapiro 	/* Note: this error is shown to the client, so do not "leak" info */
809d39bd2c1SGregory Neil Shapiro 	usrerr("451 4.3.1 temporary error");
810d39bd2c1SGregory Neil Shapiro 
811d39bd2c1SGregory Neil Shapiro 	return false;
812d39bd2c1SGregory Neil Shapiro #endif
813c2aa98e2SPeter Wemm }
814