Update zoneinfo database.
[dragonfly/netmp.git] / contrib / sendmail / src / macro.c
blobfc7a2c277c84c61f76e9b5f393044f2c8e05216f
1 /*
2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
14 #include <sendmail.h>
16 SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro Exp $")
18 #if MAXMACROID != (BITMAPBITS - 1)
19 ERROR Read the comment in conf.h
20 #endif /* MAXMACROID != (BITMAPBITS - 1) */
22 static char *MacroName[MAXMACROID + 1]; /* macro id to name table */
23 int NextMacroId = 0240; /* codes for long named macros */
26 ** INITMACROS -- initialize the macro system
28 ** This just involves defining some macros that are actually
29 ** used internally as metasymbols to be themselves.
31 ** Parameters:
32 ** none.
34 ** Returns:
35 ** none.
37 ** Side Effects:
38 ** initializes several macros to be themselves.
41 struct metamac MetaMacros[] =
43 /* LHS pattern matching characters */
44 { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE },
45 { '=', MATCHCLASS }, { '~', MATCHNCLASS },
47 /* these are RHS metasymbols */
48 { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER },
49 { '>', CALLSUBR },
51 /* the conditional operations */
52 { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI },
54 /* the hostname lookup characters */
55 { '[', HOSTBEGIN }, { ']', HOSTEND },
56 { '(', LOOKUPBEGIN }, { ')', LOOKUPEND },
58 /* miscellaneous control characters */
59 { '&', MACRODEXPAND },
61 { '\0', '\0' }
64 #define MACBINDING(name, mid) \
65 stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
66 MacroName[mid] = name;
68 void
69 initmacros(e)
70 register ENVELOPE *e;
72 register struct metamac *m;
73 register int c;
74 char buf[5];
76 for (m = MetaMacros; m->metaname != '\0'; m++)
78 buf[0] = m->metaval;
79 buf[1] = '\0';
80 macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
82 buf[0] = MATCHREPL;
83 buf[2] = '\0';
84 for (c = '0'; c <= '9'; c++)
86 buf[1] = c;
87 macdefine(&e->e_macro, A_TEMP, c, buf);
90 /* set defaults for some macros sendmail will use later */
91 macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
93 /* set up external names for some internal macros */
94 MACBINDING("opMode", MID_OPMODE);
95 /*XXX should probably add equivalents for all short macros here XXX*/
98 ** EXPAND -- macro expand a string using $x escapes.
100 ** Parameters:
101 ** s -- the string to expand.
102 ** buf -- the place to put the expansion.
103 ** bufsize -- the size of the buffer.
104 ** e -- envelope in which to work.
106 ** Returns:
107 ** none.
109 ** Side Effects:
110 ** none.
113 void
114 expand(s, buf, bufsize, e)
115 register char *s;
116 register char *buf;
117 size_t bufsize;
118 register ENVELOPE *e;
120 register char *xp;
121 register char *q;
122 bool skipping; /* set if conditionally skipping output */
123 bool recurse; /* set if recursion required */
124 size_t i;
125 int skiplev; /* skipping nesting level */
126 int iflev; /* if nesting level */
127 char xbuf[MACBUFSIZE];
128 static int explevel = 0;
130 if (tTd(35, 24))
132 sm_dprintf("expand(");
133 xputs(s);
134 sm_dprintf(")\n");
137 recurse = false;
138 skipping = false;
139 skiplev = 0;
140 iflev = 0;
141 if (s == NULL)
142 s = "";
143 for (xp = xbuf; *s != '\0'; s++)
145 int c;
148 ** Check for non-ordinary (special?) character.
149 ** 'q' will be the interpolated quantity.
152 q = NULL;
153 c = *s;
154 switch (c & 0377)
156 case CONDIF: /* see if var set */
157 iflev++;
158 c = *++s;
159 if (skipping)
160 skiplev++;
161 else
163 char *mv;
165 mv = macvalue(c, e);
166 skipping = (mv == NULL || *mv == '\0');
168 continue;
170 case CONDELSE: /* change state of skipping */
171 if (iflev == 0)
172 break; /* XXX: error */
173 if (skiplev == 0)
174 skipping = !skipping;
175 continue;
177 case CONDFI: /* stop skipping */
178 if (iflev == 0)
179 break; /* XXX: error */
180 iflev--;
181 if (skiplev == 0)
182 skipping = false;
183 if (skipping)
184 skiplev--;
185 continue;
187 case MACROEXPAND: /* macro interpolation */
188 c = bitidx(*++s);
189 if (c != '\0')
190 q = macvalue(c, e);
191 else
193 s--;
194 q = NULL;
196 if (q == NULL)
197 continue;
198 break;
202 ** Interpolate q or output one character
205 if (skipping || xp >= &xbuf[sizeof xbuf - 1])
206 continue;
207 if (q == NULL)
208 *xp++ = c;
209 else
211 /* copy to end of q or max space remaining in buf */
212 while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
214 /* check for any sendmail metacharacters */
215 if ((c & 0340) == 0200)
216 recurse = true;
217 *xp++ = c;
221 *xp = '\0';
223 if (tTd(35, 24))
225 sm_dprintf("expand ==> ");
226 xputs(xbuf);
227 sm_dprintf("\n");
230 /* recurse as appropriate */
231 if (recurse)
233 if (explevel < MaxMacroRecursion)
235 explevel++;
236 expand(xbuf, buf, bufsize, e);
237 explevel--;
238 return;
240 syserr("expand: recursion too deep (%d max)",
241 MaxMacroRecursion);
244 /* copy results out */
245 i = xp - xbuf;
246 if (i >= bufsize)
247 i = bufsize - 1;
248 memmove(buf, xbuf, i);
249 buf[i] = '\0';
253 ** MACDEFINE -- bind a macro name to a value
255 ** Set a macro to a value, with fancy storage management.
256 ** macdefine will make a copy of the value, if required,
257 ** and will ensure that the storage for the previous value
258 ** is not leaked.
260 ** Parameters:
261 ** mac -- Macro table.
262 ** vclass -- storage class of 'value', ignored if value==NULL.
263 ** A_HEAP means that the value was allocated by
264 ** malloc, and that macdefine owns the storage.
265 ** A_TEMP means that value points to temporary storage,
266 ** and thus macdefine needs to make a copy.
267 ** A_PERM means that value points to storage that
268 ** will remain allocated and unchanged for
269 ** at least the lifetime of mac. Use A_PERM if:
270 ** -- value == NULL,
271 ** -- value points to a string literal,
272 ** -- value was allocated from mac->mac_rpool
273 ** or (in the case of an envelope macro)
274 ** from e->e_rpool,
275 ** -- in the case of an envelope macro,
276 ** value is a string member of the envelope
277 ** such as e->e_sender.
278 ** id -- Macro id. This is a single character macro name
279 ** such as 'g', or a value returned by macid().
280 ** value -- Macro value: either NULL, or a string.
283 void
284 #if SM_HEAP_CHECK
285 macdefine_tagged(mac, vclass, id, value, file, line, grp)
286 #else /* SM_HEAP_CHECK */
287 macdefine(mac, vclass, id, value)
288 #endif /* SM_HEAP_CHECK */
289 MACROS_T *mac;
290 ARGCLASS_T vclass;
291 int id;
292 char *value;
293 #if SM_HEAP_CHECK
294 char *file;
295 int line;
296 int grp;
297 #endif /* SM_HEAP_CHECK */
299 char *newvalue;
301 if (id < 0 || id > MAXMACROID)
302 return;
304 if (tTd(35, 9))
306 sm_dprintf("%sdefine(%s as ",
307 mac->mac_table[id] == NULL ? "" : "re", macname(id));
308 xputs(value);
309 sm_dprintf(")\n");
312 if (mac->mac_rpool == NULL)
314 char *freeit = NULL;
316 if (mac->mac_table[id] != NULL &&
317 bitnset(id, mac->mac_allocated))
318 freeit = mac->mac_table[id];
320 if (value == NULL || vclass == A_HEAP)
322 sm_heap_checkptr_tagged(value, file, line);
323 newvalue = value;
324 clrbitn(id, mac->mac_allocated);
326 else
328 newvalue = sm_strdup_tagged_x(value, file, line, 0);
329 setbitn(id, mac->mac_allocated);
331 mac->mac_table[id] = newvalue;
332 if (freeit != NULL)
333 sm_free(freeit);
335 else
337 if (value == NULL || vclass == A_PERM)
338 newvalue = value;
339 else
340 newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
341 mac->mac_table[id] = newvalue;
342 if (vclass == A_HEAP)
343 sm_free(value);
346 #if _FFR_RESET_MACRO_GLOBALS
347 switch (id)
349 case 'j':
350 PSTRSET(MyHostName, value);
351 break;
353 #endif /* _FFR_RESET_MACRO_GLOBALS */
357 ** MACSET -- set a named macro to a value (low level)
359 ** No fancy storage management; the caller takes full responsibility.
360 ** Often used with macget; see also macdefine.
362 ** Parameters:
363 ** mac -- Macro table.
364 ** i -- Macro name, specified as an integer offset.
365 ** value -- Macro value: either NULL, or a string.
368 void
369 macset(mac, i, value)
370 MACROS_T *mac;
371 int i;
372 char *value;
374 if (i < 0 || i > MAXMACROID)
375 return;
377 if (tTd(35, 9))
379 sm_dprintf("macset(%s as ", macname(i));
380 xputs(value);
381 sm_dprintf(")\n");
383 mac->mac_table[i] = value;
387 ** MACVALUE -- return uninterpreted value of a macro.
389 ** Does fancy path searching.
390 ** The low level counterpart is macget.
392 ** Parameters:
393 ** n -- the name of the macro.
394 ** e -- envelope in which to start looking for the macro.
396 ** Returns:
397 ** The value of n.
399 ** Side Effects:
400 ** none.
403 char *
404 macvalue(n, e)
405 int n;
406 register ENVELOPE *e;
408 n = bitidx(n);
409 if (e != NULL && e->e_mci != NULL)
411 register char *p = e->e_mci->mci_macro.mac_table[n];
413 if (p != NULL)
414 return p;
416 while (e != NULL)
418 register char *p = e->e_macro.mac_table[n];
420 if (p != NULL)
421 return p;
422 if (e == e->e_parent)
423 break;
424 e = e->e_parent;
426 return GlobalMacros.mac_table[n];
429 ** MACNAME -- return the name of a macro given its internal id
431 ** Parameter:
432 ** n -- the id of the macro
434 ** Returns:
435 ** The name of n.
437 ** Side Effects:
438 ** none.
441 char *
442 macname(n)
443 int n;
445 static char mbuf[2];
447 n = bitidx(n);
448 if (bitset(0200, n))
450 char *p = MacroName[n];
452 if (p != NULL)
453 return p;
454 return "***UNDEFINED MACRO***";
456 mbuf[0] = n;
457 mbuf[1] = '\0';
458 return mbuf;
461 ** MACID_PARSE -- return id of macro identified by its name
463 ** Parameters:
464 ** p -- pointer to name string -- either a single
465 ** character or {name}.
466 ** ep -- filled in with the pointer to the byte
467 ** after the name.
469 ** Returns:
470 ** 0 -- An error was detected.
471 ** 1..255 -- The internal id code for this macro.
473 ** Side Effects:
474 ** If this is a new macro name, a new id is allocated.
475 ** On error, syserr is called.
479 macid_parse(p, ep)
480 register char *p;
481 char **ep;
483 int mid;
484 register char *bp;
485 char mbuf[MAXMACNAMELEN + 1];
487 if (tTd(35, 14))
489 sm_dprintf("macid(");
490 xputs(p);
491 sm_dprintf(") => ");
494 if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
496 syserr("Name required for macro/class");
497 if (ep != NULL)
498 *ep = p;
499 if (tTd(35, 14))
500 sm_dprintf("NULL\n");
501 return 0;
503 if (*p != '{')
505 /* the macro is its own code */
506 if (ep != NULL)
507 *ep = p + 1;
508 if (tTd(35, 14))
509 sm_dprintf("%c\n", bitidx(*p));
510 return bitidx(*p);
512 bp = mbuf;
513 while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
515 if (isascii(*p) && (isalnum(*p) || *p == '_'))
516 *bp++ = *p;
517 else
518 syserr("Invalid macro/class character %c", *p);
520 *bp = '\0';
521 mid = -1;
522 if (*p == '\0')
524 syserr("Unbalanced { on %s", mbuf); /* missing } */
526 else if (*p != '}')
528 syserr("Macro/class name ({%s}) too long (%d chars max)",
529 mbuf, (int) (sizeof mbuf - 1));
531 else if (mbuf[1] == '\0')
533 /* ${x} == $x */
534 mid = bitidx(mbuf[0]);
535 p++;
537 else
539 register STAB *s;
541 s = stab(mbuf, ST_MACRO, ST_ENTER);
542 if (s->s_macro != 0)
543 mid = s->s_macro;
544 else
546 if (NextMacroId > MAXMACROID)
548 syserr("Macro/class {%s}: too many long names",
549 mbuf);
550 s->s_macro = -1;
552 else
554 MacroName[NextMacroId] = s->s_name;
555 s->s_macro = mid = NextMacroId++;
558 p++;
560 if (ep != NULL)
561 *ep = p;
562 if (mid < 0 || mid > MAXMACROID)
564 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
565 if (tTd(35, 14))
566 sm_dprintf("NULL\n");
567 return 0;
569 if (tTd(35, 14))
570 sm_dprintf("0x%x\n", mid);
571 return mid;
574 ** WORDINCLASS -- tell if a word is in a specific class
576 ** Parameters:
577 ** str -- the name of the word to look up.
578 ** cl -- the class name.
580 ** Returns:
581 ** true if str can be found in cl.
582 ** false otherwise.
585 bool
586 wordinclass(str, cl)
587 char *str;
588 int cl;
590 register STAB *s;
592 s = stab(str, ST_CLASS, ST_FIND);
593 return s != NULL && bitnset(bitidx(cl), s->s_class);