Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / sendmail / src / macro.c
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.
7  *
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.
11  *
12  */
13
14 #include <sendmail.h>
15
16 SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro Exp $")
17
18 #if MAXMACROID != (BITMAPBITS - 1)
19         ERROR Read the comment in conf.h
20 #endif /* MAXMACROID != (BITMAPBITS - 1) */
21
22 static char     *MacroName[MAXMACROID + 1];     /* macro id to name table */
23 int             NextMacroId = 0240;     /* codes for long named macros */
24
25 /*
26 **  INITMACROS -- initialize the macro system
27 **
28 **      This just involves defining some macros that are actually
29 **      used internally as metasymbols to be themselves.
30 **
31 **      Parameters:
32 **              none.
33 **
34 **      Returns:
35 **              none.
36 **
37 **      Side Effects:
38 **              initializes several macros to be themselves.
39 */
40
41 struct metamac  MetaMacros[] =
42 {
43         /* LHS pattern matching characters */
44         { '*', MATCHZANY },     { '+', MATCHANY },      { '-', MATCHONE },
45         { '=', MATCHCLASS },    { '~', MATCHNCLASS },
46
47         /* these are RHS metasymbols */
48         { '#', CANONNET },      { '@', CANONHOST },     { ':', CANONUSER },
49         { '>', CALLSUBR },
50
51         /* the conditional operations */
52         { '?', CONDIF },        { '|', CONDELSE },      { '.', CONDFI },
53
54         /* the hostname lookup characters */
55         { '[', HOSTBEGIN },     { ']', HOSTEND },
56         { '(', LOOKUPBEGIN },   { ')', LOOKUPEND },
57
58         /* miscellaneous control characters */
59         { '&', MACRODEXPAND },
60
61         { '\0', '\0' }
62 };
63
64 #define MACBINDING(name, mid) \
65                 stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
66                 MacroName[mid] = name;
67
68 void
69 initmacros(e)
70         register ENVELOPE *e;
71 {
72         register struct metamac *m;
73         register int c;
74         char buf[5];
75
76         for (m = MetaMacros; m->metaname != '\0'; m++)
77         {
78                 buf[0] = m->metaval;
79                 buf[1] = '\0';
80                 macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
81         }
82         buf[0] = MATCHREPL;
83         buf[2] = '\0';
84         for (c = '0'; c <= '9'; c++)
85         {
86                 buf[1] = c;
87                 macdefine(&e->e_macro, A_TEMP, c, buf);
88         }
89
90         /* set defaults for some macros sendmail will use later */
91         macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
92
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*/
96 }
97 /*
98 **  EXPAND -- macro expand a string using $x escapes.
99 **
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.
105 **
106 **      Returns:
107 **              none.
108 **
109 **      Side Effects:
110 **              none.
111 */
112
113 void
114 expand(s, buf, bufsize, e)
115         register char *s;
116         register char *buf;
117         size_t bufsize;
118         register ENVELOPE *e;
119 {
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;
129
130         if (tTd(35, 24))
131         {
132                 sm_dprintf("expand(");
133                 xputs(s);
134                 sm_dprintf(")\n");
135         }
136
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++)
144         {
145                 int c;
146
147                 /*
148                 **  Check for non-ordinary (special?) character.
149                 **      'q' will be the interpolated quantity.
150                 */
151
152                 q = NULL;
153                 c = *s;
154                 switch (c & 0377)
155                 {
156                   case CONDIF:          /* see if var set */
157                         iflev++;
158                         c = *++s;
159                         if (skipping)
160                                 skiplev++;
161                         else
162                         {
163                                 char *mv;
164
165                                 mv = macvalue(c, e);
166                                 skipping = (mv == NULL || *mv == '\0');
167                         }
168                         continue;
169
170                   case CONDELSE:        /* change state of skipping */
171                         if (iflev == 0)
172                                 break;  /* XXX: error */
173                         if (skiplev == 0)
174                                 skipping = !skipping;
175                         continue;
176
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;
186
187                   case MACROEXPAND:     /* macro interpolation */
188                         c = bitidx(*++s);
189                         if (c != '\0')
190                                 q = macvalue(c, e);
191                         else
192                         {
193                                 s--;
194                                 q = NULL;
195                         }
196                         if (q == NULL)
197                                 continue;
198                         break;
199                 }
200
201                 /*
202                 **  Interpolate q or output one character
203                 */
204
205                 if (skipping || xp >= &xbuf[sizeof xbuf - 1])
206                         continue;
207                 if (q == NULL)
208                         *xp++ = c;
209                 else
210                 {
211                         /* copy to end of q or max space remaining in buf */
212                         while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
213                         {
214                                 /* check for any sendmail metacharacters */
215                                 if ((c & 0340) == 0200)
216                                         recurse = true;
217                                 *xp++ = c;
218                         }
219                 }
220         }
221         *xp = '\0';
222
223         if (tTd(35, 24))
224         {
225                 sm_dprintf("expand ==> ");
226                 xputs(xbuf);
227                 sm_dprintf("\n");
228         }
229
230         /* recurse as appropriate */
231         if (recurse)
232         {
233                 if (explevel < MaxMacroRecursion)
234                 {
235                         explevel++;
236                         expand(xbuf, buf, bufsize, e);
237                         explevel--;
238                         return;
239                 }
240                 syserr("expand: recursion too deep (%d max)",
241                         MaxMacroRecursion);
242         }
243
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';
250 }
251
252 /*
253 **  MACDEFINE -- bind a macro name to a value
254 **
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.
259 **
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.
281 */
282
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 */
298 {
299         char *newvalue;
300
301         if (id < 0 || id > MAXMACROID)
302                 return;
303
304         if (tTd(35, 9))
305         {
306                 sm_dprintf("%sdefine(%s as ",
307                         mac->mac_table[id] == NULL ? "" : "re", macname(id));
308                 xputs(value);
309                 sm_dprintf(")\n");
310         }
311
312         if (mac->mac_rpool == NULL)
313         {
314                 char *freeit = NULL;
315
316                 if (mac->mac_table[id] != NULL &&
317                     bitnset(id, mac->mac_allocated))
318                         freeit = mac->mac_table[id];
319
320                 if (value == NULL || vclass == A_HEAP)
321                 {
322                         sm_heap_checkptr_tagged(value, file, line);
323                         newvalue = value;
324                         clrbitn(id, mac->mac_allocated);
325                 }
326                 else
327                 {
328                         newvalue = sm_strdup_tagged_x(value, file, line, 0);
329                         setbitn(id, mac->mac_allocated);
330                 }
331                 mac->mac_table[id] = newvalue;
332                 if (freeit != NULL)
333                         sm_free(freeit);
334         }
335         else
336         {
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);
344         }
345
346 #if _FFR_RESET_MACRO_GLOBALS
347         switch (id)
348         {
349           case 'j':
350                 PSTRSET(MyHostName, value);
351                 break;
352         }
353 #endif /* _FFR_RESET_MACRO_GLOBALS */
354 }
355
356 /*
357 **  MACSET -- set a named macro to a value (low level)
358 **
359 **      No fancy storage management; the caller takes full responsibility.
360 **      Often used with macget; see also macdefine.
361 **
362 **      Parameters:
363 **              mac -- Macro table.
364 **              i -- Macro name, specified as an integer offset.
365 **              value -- Macro value: either NULL, or a string.
366 */
367
368 void
369 macset(mac, i, value)
370         MACROS_T *mac;
371         int i;
372         char *value;
373 {
374         if (i < 0 || i > MAXMACROID)
375                 return;
376
377         if (tTd(35, 9))
378         {
379                 sm_dprintf("macset(%s as ", macname(i));
380                 xputs(value);
381                 sm_dprintf(")\n");
382         }
383         mac->mac_table[i] = value;
384 }
385
386 /*
387 **  MACVALUE -- return uninterpreted value of a macro.
388 **
389 **      Does fancy path searching.
390 **      The low level counterpart is macget.
391 **
392 **      Parameters:
393 **              n -- the name of the macro.
394 **              e -- envelope in which to start looking for the macro.
395 **
396 **      Returns:
397 **              The value of n.
398 **
399 **      Side Effects:
400 **              none.
401 */
402
403 char *
404 macvalue(n, e)
405         int n;
406         register ENVELOPE *e;
407 {
408         n = bitidx(n);
409         if (e != NULL && e->e_mci != NULL)
410         {
411                 register char *p = e->e_mci->mci_macro.mac_table[n];
412
413                 if (p != NULL)
414                         return p;
415         }
416         while (e != NULL)
417         {
418                 register char *p = e->e_macro.mac_table[n];
419
420                 if (p != NULL)
421                         return p;
422                 if (e == e->e_parent)
423                         break;
424                 e = e->e_parent;
425         }
426         return GlobalMacros.mac_table[n];
427 }
428 /*
429 **  MACNAME -- return the name of a macro given its internal id
430 **
431 **      Parameter:
432 **              n -- the id of the macro
433 **
434 **      Returns:
435 **              The name of n.
436 **
437 **      Side Effects:
438 **              none.
439 */
440
441 char *
442 macname(n)
443         int n;
444 {
445         static char mbuf[2];
446
447         n = bitidx(n);
448         if (bitset(0200, n))
449         {
450                 char *p = MacroName[n];
451
452                 if (p != NULL)
453                         return p;
454                 return "***UNDEFINED MACRO***";
455         }
456         mbuf[0] = n;
457         mbuf[1] = '\0';
458         return mbuf;
459 }
460 /*
461 **  MACID_PARSE -- return id of macro identified by its name
462 **
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.
468 **
469 **      Returns:
470 **              0 -- An error was detected.
471 **              1..255 -- The internal id code for this macro.
472 **
473 **      Side Effects:
474 **              If this is a new macro name, a new id is allocated.
475 **              On error, syserr is called.
476 */
477
478 int
479 macid_parse(p, ep)
480         register char *p;
481         char **ep;
482 {
483         int mid;
484         register char *bp;
485         char mbuf[MAXMACNAMELEN + 1];
486
487         if (tTd(35, 14))
488         {
489                 sm_dprintf("macid(");
490                 xputs(p);
491                 sm_dprintf(") => ");
492         }
493
494         if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
495         {
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;
502         }
503         if (*p != '{')
504         {
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);
511         }
512         bp = mbuf;
513         while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
514         {
515                 if (isascii(*p) && (isalnum(*p) || *p == '_'))
516                         *bp++ = *p;
517                 else
518                         syserr("Invalid macro/class character %c", *p);
519         }
520         *bp = '\0';
521         mid = -1;
522         if (*p == '\0')
523         {
524                 syserr("Unbalanced { on %s", mbuf);     /* missing } */
525         }
526         else if (*p != '}')
527         {
528                 syserr("Macro/class name ({%s}) too long (%d chars max)",
529                         mbuf, (int) (sizeof mbuf - 1));
530         }
531         else if (mbuf[1] == '\0')
532         {
533                 /* ${x} == $x */
534                 mid = bitidx(mbuf[0]);
535                 p++;
536         }
537         else
538         {
539                 register STAB *s;
540
541                 s = stab(mbuf, ST_MACRO, ST_ENTER);
542                 if (s->s_macro != 0)
543                         mid = s->s_macro;
544                 else
545                 {
546                         if (NextMacroId > MAXMACROID)
547                         {
548                                 syserr("Macro/class {%s}: too many long names",
549                                         mbuf);
550                                 s->s_macro = -1;
551                         }
552                         else
553                         {
554                                 MacroName[NextMacroId] = s->s_name;
555                                 s->s_macro = mid = NextMacroId++;
556                         }
557                 }
558                 p++;
559         }
560         if (ep != NULL)
561                 *ep = p;
562         if (mid < 0 || mid > MAXMACROID)
563         {
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;
568         }
569         if (tTd(35, 14))
570                 sm_dprintf("0x%x\n", mid);
571         return mid;
572 }
573 /*
574 **  WORDINCLASS -- tell if a word is in a specific class
575 **
576 **      Parameters:
577 **              str -- the name of the word to look up.
578 **              cl -- the class name.
579 **
580 **      Returns:
581 **              true if str can be found in cl.
582 **              false otherwise.
583 */
584
585 bool
586 wordinclass(str, cl)
587         char *str;
588         int cl;
589 {
590         register STAB *s;
591
592         s = stab(str, ST_CLASS, ST_FIND);
593         return s != NULL && bitnset(bitidx(cl), s->s_class);
594 }