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