Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / sendmail / macro.c
1 /*
2  * Copyright (c) 1998-2001, 2003 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.88 2003/09/05 23:11:18 ca 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(sm_debug_file(), 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(sm_debug_file(), 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(sm_debug_file(), 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 #if SM_HEAP_CHECK
329                         newvalue = sm_strdup_tagged_x(value, file, line, 0);
330 #else /* SM_HEAP_CHECK */
331                         newvalue = sm_strdup_x(value);
332 #endif /* SM_HEAP_CHECK */
333                         setbitn(id, mac->mac_allocated);
334                 }
335                 mac->mac_table[id] = newvalue;
336                 if (freeit != NULL)
337                         sm_free(freeit);
338         }
339         else
340         {
341                 if (value == NULL || vclass == A_PERM)
342                         newvalue = value;
343                 else
344                         newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
345                 mac->mac_table[id] = newvalue;
346                 if (vclass == A_HEAP)
347                         sm_free(value);
348         }
349
350 #if _FFR_RESET_MACRO_GLOBALS
351         switch (id)
352         {
353           case 'j':
354                 PSTRSET(MyHostName, value);
355                 break;
356         }
357 #endif /* _FFR_RESET_MACRO_GLOBALS */
358 }
359
360 /*
361 **  MACSET -- set a named macro to a value (low level)
362 **
363 **      No fancy storage management; the caller takes full responsibility.
364 **      Often used with macget; see also macdefine.
365 **
366 **      Parameters:
367 **              mac -- Macro table.
368 **              i -- Macro name, specified as an integer offset.
369 **              value -- Macro value: either NULL, or a string.
370 */
371
372 void
373 macset(mac, i, value)
374         MACROS_T *mac;
375         int i;
376         char *value;
377 {
378         if (i < 0 || i > MAXMACROID)
379                 return;
380
381         if (tTd(35, 9))
382         {
383                 sm_dprintf("macset(%s as ", macname(i));
384                 xputs(sm_debug_file(), value);
385                 sm_dprintf(")\n");
386         }
387         mac->mac_table[i] = value;
388 }
389
390 /*
391 **  MACVALUE -- return uninterpreted value of a macro.
392 **
393 **      Does fancy path searching.
394 **      The low level counterpart is macget.
395 **
396 **      Parameters:
397 **              n -- the name of the macro.
398 **              e -- envelope in which to start looking for the macro.
399 **
400 **      Returns:
401 **              The value of n.
402 **
403 **      Side Effects:
404 **              none.
405 */
406
407 char *
408 macvalue(n, e)
409         int n;
410         register ENVELOPE *e;
411 {
412         n = bitidx(n);
413         if (e != NULL && e->e_mci != NULL)
414         {
415                 register char *p = e->e_mci->mci_macro.mac_table[n];
416
417                 if (p != NULL)
418                         return p;
419         }
420         while (e != NULL)
421         {
422                 register char *p = e->e_macro.mac_table[n];
423
424                 if (p != NULL)
425                         return p;
426                 if (e == e->e_parent)
427                         break;
428                 e = e->e_parent;
429         }
430         return GlobalMacros.mac_table[n];
431 }
432 /*
433 **  MACNAME -- return the name of a macro given its internal id
434 **
435 **      Parameter:
436 **              n -- the id of the macro
437 **
438 **      Returns:
439 **              The name of n.
440 **
441 **      Side Effects:
442 **              none.
443 */
444
445 char *
446 macname(n)
447         int n;
448 {
449         static char mbuf[2];
450
451         n = bitidx(n);
452         if (bitset(0200, n))
453         {
454                 char *p = MacroName[n];
455
456                 if (p != NULL)
457                         return p;
458                 return "***UNDEFINED MACRO***";
459         }
460         mbuf[0] = n;
461         mbuf[1] = '\0';
462         return mbuf;
463 }
464 /*
465 **  MACID_PARSE -- return id of macro identified by its name
466 **
467 **      Parameters:
468 **              p -- pointer to name string -- either a single
469 **                      character or {name}.
470 **              ep -- filled in with the pointer to the byte
471 **                      after the name.
472 **
473 **      Returns:
474 **              0 -- An error was detected.
475 **              1..255 -- The internal id code for this macro.
476 **
477 **      Side Effects:
478 **              If this is a new macro name, a new id is allocated.
479 **              On error, syserr is called.
480 */
481
482 int
483 macid_parse(p, ep)
484         register char *p;
485         char **ep;
486 {
487         int mid;
488         register char *bp;
489         char mbuf[MAXMACNAMELEN + 1];
490
491         if (tTd(35, 14))
492         {
493                 sm_dprintf("macid(");
494                 xputs(sm_debug_file(), p);
495                 sm_dprintf(") => ");
496         }
497
498         if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
499         {
500                 syserr("Name required for macro/class");
501                 if (ep != NULL)
502                         *ep = p;
503                 if (tTd(35, 14))
504                         sm_dprintf("NULL\n");
505                 return 0;
506         }
507         if (*p != '{')
508         {
509                 /* the macro is its own code */
510                 if (ep != NULL)
511                         *ep = p + 1;
512                 if (tTd(35, 14))
513                         sm_dprintf("%c\n", bitidx(*p));
514                 return bitidx(*p);
515         }
516         bp = mbuf;
517         while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1])
518         {
519                 if (isascii(*p) && (isalnum(*p) || *p == '_'))
520                         *bp++ = *p;
521                 else
522                         syserr("Invalid macro/class character %c", *p);
523         }
524         *bp = '\0';
525         mid = -1;
526         if (*p == '\0')
527         {
528                 syserr("Unbalanced { on %s", mbuf);     /* missing } */
529         }
530         else if (*p != '}')
531         {
532                 syserr("Macro/class name ({%s}) too long (%d chars max)",
533                         mbuf, (int) (sizeof mbuf - 1));
534         }
535         else if (mbuf[1] == '\0')
536         {
537                 /* ${x} == $x */
538                 mid = bitidx(mbuf[0]);
539                 p++;
540         }
541         else
542         {
543                 register STAB *s;
544
545                 s = stab(mbuf, ST_MACRO, ST_ENTER);
546                 if (s->s_macro != 0)
547                         mid = s->s_macro;
548                 else
549                 {
550                         if (NextMacroId > MAXMACROID)
551                         {
552                                 syserr("Macro/class {%s}: too many long names",
553                                         mbuf);
554                                 s->s_macro = -1;
555                         }
556                         else
557                         {
558                                 MacroName[NextMacroId] = s->s_name;
559                                 s->s_macro = mid = NextMacroId++;
560                         }
561                 }
562                 p++;
563         }
564         if (ep != NULL)
565                 *ep = p;
566         if (mid < 0 || mid > MAXMACROID)
567         {
568                 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
569                 if (tTd(35, 14))
570                         sm_dprintf("NULL\n");
571                 return 0;
572         }
573         if (tTd(35, 14))
574                 sm_dprintf("0x%x\n", mid);
575         return mid;
576 }
577 /*
578 **  WORDINCLASS -- tell if a word is in a specific class
579 **
580 **      Parameters:
581 **              str -- the name of the word to look up.
582 **              cl -- the class name.
583 **
584 **      Returns:
585 **              true if str can be found in cl.
586 **              false otherwise.
587 */
588
589 bool
590 wordinclass(str, cl)
591         char *str;
592         int cl;
593 {
594         register STAB *s;
595
596         s = stab(str, ST_CLASS, ST_FIND);
597         return s != NULL && bitnset(bitidx(cl), s->s_class);
598 }