]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/src/macro.c
This commit was generated by cvs2svn to compensate for changes in r172668,
[FreeBSD/FreeBSD.git] / contrib / sendmail / src / macro.c
1 /*
2  * Copyright (c) 1998-2001, 2003, 2006 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.102 2006/12/21 23:06:10 ca Exp $")
17
18 #include <sm/sendmail.h>
19 #if MAXMACROID != (BITMAPBITS - 1)
20         ERROR Read the comment in conf.h
21 #endif /* MAXMACROID != (BITMAPBITS - 1) */
22
23 static char     *MacroName[MAXMACROID + 1];     /* macro id to name table */
24 int             NextMacroId = 0240;     /* codes for long named macros */
25 /* see sendmail.h: Special characters in rewriting rules. */
26
27
28 /*
29 **  INITMACROS -- initialize the macro system
30 **
31 **      This just involves defining some macros that are actually
32 **      used internally as metasymbols to be themselves.
33 **
34 **      Parameters:
35 **              none.
36 **
37 **      Returns:
38 **              none.
39 **
40 **      Side Effects:
41 **              initializes several macros to be themselves.
42 */
43
44 struct metamac  MetaMacros[] =
45 {
46         /* LHS pattern matching characters */
47         { '*', MATCHZANY },     { '+', MATCHANY },      { '-', MATCHONE },
48         { '=', MATCHCLASS },    { '~', MATCHNCLASS },
49
50         /* these are RHS metasymbols */
51         { '#', CANONNET },      { '@', CANONHOST },     { ':', CANONUSER },
52         { '>', CALLSUBR },
53
54         /* the conditional operations */
55         { '?', CONDIF },        { '|', CONDELSE },      { '.', CONDFI },
56
57         /* the hostname lookup characters */
58         { '[', HOSTBEGIN },     { ']', HOSTEND },
59         { '(', LOOKUPBEGIN },   { ')', LOOKUPEND },
60
61         /* miscellaneous control characters */
62         { '&', MACRODEXPAND },
63
64         { '\0', '\0' }
65 };
66
67 #define MACBINDING(name, mid) \
68                 stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
69                 MacroName[mid] = name;
70
71 void
72 initmacros(e)
73         ENVELOPE *e;
74 {
75         struct metamac *m;
76         int c;
77         char buf[5];
78
79         for (m = MetaMacros; m->metaname != '\0'; m++)
80         {
81                 buf[0] = m->metaval;
82                 buf[1] = '\0';
83                 macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
84         }
85         buf[0] = MATCHREPL;
86         buf[2] = '\0';
87         for (c = '0'; c <= '9'; c++)
88         {
89                 buf[1] = c;
90                 macdefine(&e->e_macro, A_TEMP, c, buf);
91         }
92
93         /* set defaults for some macros sendmail will use later */
94         macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
95
96         /* set up external names for some internal macros */
97         MACBINDING("opMode", MID_OPMODE);
98         /*XXX should probably add equivalents for all short macros here XXX*/
99 }
100
101 /*
102 **  EXPAND/DOEXPAND -- macro expand a string using $x escapes.
103 **
104 **      After expansion, the expansion will be in external form (that is,
105 **      there will be no sendmail metacharacters and METAQUOTEs will have
106 **      been stripped out).
107 **
108 **      Parameters:
109 **              s -- the string to expand.
110 **              buf -- the place to put the expansion.
111 **              bufsize -- the size of the buffer.
112 **              explevel -- the depth of expansion (doexpand only)
113 **              e -- envelope in which to work.
114 **
115 **      Returns:
116 **              none.
117 **
118 **      Side Effects:
119 **              none.
120 */
121
122 static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *));
123
124 static void
125 doexpand(s, buf, bufsize, explevel, e)
126         char *s;
127         char *buf;
128         size_t bufsize;
129         int explevel;
130         ENVELOPE *e;
131 {
132         char *xp;
133         char *q;
134         bool skipping;          /* set if conditionally skipping output */
135         bool recurse;           /* set if recursion required */
136         size_t i;
137         int skiplev;            /* skipping nesting level */
138         int iflev;              /* if nesting level */
139         bool quotenext;         /* quote the following character */
140         char xbuf[MACBUFSIZE];
141
142         if (tTd(35, 24))
143         {
144                 sm_dprintf("expand(");
145                 xputs(sm_debug_file(), s);
146                 sm_dprintf(")\n");
147         }
148
149         recurse = false;
150         skipping = false;
151         skiplev = 0;
152         iflev = 0;
153         quotenext = false;
154         if (s == NULL)
155                 s = "";
156         for (xp = xbuf; *s != '\0'; s++)
157         {
158                 int c;
159
160                 /*
161                 **  Check for non-ordinary (special?) character.
162                 **      'q' will be the interpolated quantity.
163                 */
164
165                 q = NULL;
166                 c = *s & 0377;
167
168                 if (quotenext)
169                 {
170                         quotenext = false;
171                         goto simpleinterpolate;
172                 }
173
174                 switch (c)
175                 {
176                   case CONDIF:          /* see if var set */
177                         iflev++;
178                         c = *++s & 0377;
179                         if (skipping)
180                                 skiplev++;
181                         else
182                         {
183                                 char *mv;
184
185                                 mv = macvalue(c, e);
186                                 skipping = (mv == NULL || *mv == '\0');
187                         }
188                         continue;
189
190                   case CONDELSE:        /* change state of skipping */
191                         if (iflev == 0)
192                                 break;  /* XXX: error */
193                         if (skiplev == 0)
194                                 skipping = !skipping;
195                         continue;
196
197                   case CONDFI:          /* stop skipping */
198                         if (iflev == 0)
199                                 break;  /* XXX: error */
200                         iflev--;
201                         if (skiplev == 0)
202                                 skipping = false;
203                         if (skipping)
204                                 skiplev--;
205                         continue;
206
207                   case MACROEXPAND:     /* macro interpolation */
208                         c = bitidx(*++s);
209                         if (c != '\0')
210                                 q = macvalue(c, e);
211                         else
212                         {
213                                 s--;
214                                 q = NULL;
215                         }
216                         if (q == NULL)
217                                 continue;
218                         break;
219
220                   case METAQUOTE:
221                         /* next octet completely quoted */
222                         quotenext = true;
223                         break;
224                 }
225
226                 /*
227                 **  Interpolate q or output one character
228                 */
229
230   simpleinterpolate:
231                 if (skipping || xp >= &xbuf[sizeof(xbuf) - 1])
232                         continue;
233                 if (q == NULL)
234                         *xp++ = c;
235                 else
236                 {
237                         /* copy to end of q or max space remaining in buf */
238                         bool hiderecurse = false;
239
240                         while ((c = *q++) != '\0' &&
241                                 xp < &xbuf[sizeof(xbuf) - 1])
242                         {
243                                 /* check for any sendmail metacharacters */
244                                 if (!hiderecurse && (c & 0340) == 0200)
245                                         recurse = true;
246                                 *xp++ = c;
247
248                                 /* give quoted characters a free ride */
249                                 hiderecurse = (c & 0377) == METAQUOTE;
250                         }
251                 }
252         }
253         *xp = '\0';
254
255         if (tTd(35, 28))
256         {
257                 sm_dprintf("expand(%d) ==> ", explevel);
258                 xputs(sm_debug_file(), xbuf);
259                 sm_dprintf("\n");
260         }
261
262         /* recurse as appropriate */
263         if (recurse)
264         {
265                 if (explevel < MaxMacroRecursion)
266                 {
267                         doexpand(xbuf, buf, bufsize, explevel + 1, e);
268                         return;
269                 }
270                 syserr("expand: recursion too deep (%d max)",
271                         MaxMacroRecursion);
272         }
273
274         /* copy results out */
275         if (explevel == 0)
276                 (void) sm_strlcpy(buf, xbuf, bufsize);
277         else
278         {
279                 /* leave in internal form */
280                 i = xp - xbuf;
281                 if (i >= bufsize)
282                         i = bufsize - 1;
283                 memmove(buf, xbuf, i);
284                 buf[i] = '\0';
285         }
286
287         if (tTd(35, 24))
288         {
289                 sm_dprintf("expand ==> ");
290                 xputs(sm_debug_file(), buf);
291                 sm_dprintf("\n");
292         }
293 }
294
295 void
296 expand(s, buf, bufsize, e)
297         char *s;
298         char *buf;
299         size_t bufsize;
300         ENVELOPE *e;
301 {
302         doexpand(s, buf, bufsize, 0, e);
303 }
304
305 /*
306 **  MACDEFINE -- bind a macro name to a value
307 **
308 **      Set a macro to a value, with fancy storage management.
309 **      macdefine will make a copy of the value, if required,
310 **      and will ensure that the storage for the previous value
311 **      is not leaked.
312 **
313 **      Parameters:
314 **              mac -- Macro table.
315 **              vclass -- storage class of 'value', ignored if value==NULL.
316 **                      A_HEAP  means that the value was allocated by
317 **                              malloc, and that macdefine owns the storage.
318 **                      A_TEMP  means that value points to temporary storage,
319 **                              and thus macdefine needs to make a copy.
320 **                      A_PERM  means that value points to storage that
321 **                              will remain allocated and unchanged for
322 **                              at least the lifetime of mac.  Use A_PERM if:
323 **                              -- value == NULL,
324 **                              -- value points to a string literal,
325 **                              -- value was allocated from mac->mac_rpool
326 **                                 or (in the case of an envelope macro)
327 **                                 from e->e_rpool,
328 **                              -- in the case of an envelope macro,
329 **                                 value is a string member of the envelope
330 **                                 such as e->e_sender.
331 **              id -- Macro id.  This is a single character macro name
332 **                      such as 'g', or a value returned by macid().
333 **              value -- Macro value: either NULL, or a string.
334 */
335
336 void
337 #if SM_HEAP_CHECK
338 macdefine_tagged(mac, vclass, id, value, file, line, grp)
339 #else /* SM_HEAP_CHECK */
340 macdefine(mac, vclass, id, value)
341 #endif /* SM_HEAP_CHECK */
342         MACROS_T *mac;
343         ARGCLASS_T vclass;
344         int id;
345         char *value;
346 #if SM_HEAP_CHECK
347         char *file;
348         int line;
349         int grp;
350 #endif /* SM_HEAP_CHECK */
351 {
352         char *newvalue;
353
354         if (id < 0 || id > MAXMACROID)
355                 return;
356
357         if (tTd(35, 9))
358         {
359                 sm_dprintf("%sdefine(%s as ",
360                         mac->mac_table[id] == NULL ? "" : "re", macname(id));
361                 xputs(sm_debug_file(), value);
362                 sm_dprintf(")\n");
363         }
364
365         if (mac->mac_rpool == NULL)
366         {
367                 char *freeit = NULL;
368
369                 if (mac->mac_table[id] != NULL &&
370                     bitnset(id, mac->mac_allocated))
371                         freeit = mac->mac_table[id];
372
373                 if (value == NULL || vclass == A_HEAP)
374                 {
375                         sm_heap_checkptr_tagged(value, file, line);
376                         newvalue = value;
377                         clrbitn(id, mac->mac_allocated);
378                 }
379                 else
380                 {
381 #if SM_HEAP_CHECK
382                         newvalue = sm_strdup_tagged_x(value, file, line, 0);
383 #else /* SM_HEAP_CHECK */
384                         newvalue = sm_strdup_x(value);
385 #endif /* SM_HEAP_CHECK */
386                         setbitn(id, mac->mac_allocated);
387                 }
388                 mac->mac_table[id] = newvalue;
389                 if (freeit != NULL)
390                         sm_free(freeit);
391         }
392         else
393         {
394                 if (value == NULL || vclass == A_PERM)
395                         newvalue = value;
396                 else
397                         newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
398                 mac->mac_table[id] = newvalue;
399                 if (vclass == A_HEAP)
400                         sm_free(value);
401         }
402
403 #if _FFR_RESET_MACRO_GLOBALS
404         switch (id)
405         {
406           case 'j':
407                 PSTRSET(MyHostName, value);
408                 break;
409         }
410 #endif /* _FFR_RESET_MACRO_GLOBALS */
411 }
412
413 /*
414 **  MACSET -- set a named macro to a value (low level)
415 **
416 **      No fancy storage management; the caller takes full responsibility.
417 **      Often used with macget; see also macdefine.
418 **
419 **      Parameters:
420 **              mac -- Macro table.
421 **              i -- Macro name, specified as an integer offset.
422 **              value -- Macro value: either NULL, or a string.
423 */
424
425 void
426 macset(mac, i, value)
427         MACROS_T *mac;
428         int i;
429         char *value;
430 {
431         if (i < 0 || i > MAXMACROID)
432                 return;
433
434         if (tTd(35, 9))
435         {
436                 sm_dprintf("macset(%s as ", macname(i));
437                 xputs(sm_debug_file(), value);
438                 sm_dprintf(")\n");
439         }
440         mac->mac_table[i] = value;
441 }
442
443 /*
444 **  MACVALUE -- return uninterpreted value of a macro.
445 **
446 **      Does fancy path searching.
447 **      The low level counterpart is macget.
448 **
449 **      Parameters:
450 **              n -- the name of the macro.
451 **              e -- envelope in which to start looking for the macro.
452 **
453 **      Returns:
454 **              The value of n.
455 **
456 **      Side Effects:
457 **              none.
458 */
459
460 char *
461 macvalue(n, e)
462         int n;
463         ENVELOPE *e;
464 {
465         n = bitidx(n);
466         if (e != NULL && e->e_mci != NULL)
467         {
468                 char *p = e->e_mci->mci_macro.mac_table[n];
469
470                 if (p != NULL)
471                         return p;
472         }
473         while (e != NULL)
474         {
475                 char *p = e->e_macro.mac_table[n];
476
477                 if (p != NULL)
478                         return p;
479                 if (e == e->e_parent)
480                         break;
481                 e = e->e_parent;
482         }
483         return GlobalMacros.mac_table[n];
484 }
485
486 /*
487 **  MACNAME -- return the name of a macro given its internal id
488 **
489 **      Parameter:
490 **              n -- the id of the macro
491 **
492 **      Returns:
493 **              The name of n.
494 **
495 **      Side Effects:
496 **              none.
497 **
498 **      WARNING:
499 **              Not thread-safe.
500 */
501
502 char *
503 macname(n)
504         int n;
505 {
506         static char mbuf[2];
507
508         n = (int)(unsigned char)n;
509         if (n > MAXMACROID)
510                 return "***OUT OF RANGE MACRO***";
511
512         /* if not ASCII printable, look up the name */
513         if (n <= 0x20 || n > 0x7f)
514         {
515                 char *p = MacroName[n];
516
517                 if (p != NULL)
518                         return p;
519                 return "***UNDEFINED MACRO***";
520         }
521
522         /* if in the ASCII graphic range, just return the id directly */
523         mbuf[0] = n;
524         mbuf[1] = '\0';
525         return mbuf;
526 }
527
528 /*
529 **  MACID_PARSE -- return id of macro identified by its name
530 **
531 **      Parameters:
532 **              p -- pointer to name string -- either a single
533 **                      character or {name}.
534 **              ep -- filled in with the pointer to the byte
535 **                      after the name.
536 **
537 **      Returns:
538 **              0 -- An error was detected.
539 **              1..MAXMACROID -- The internal id code for this macro.
540 **
541 **      Side Effects:
542 **              If this is a new macro name, a new id is allocated.
543 **              On error, syserr is called.
544 */
545
546 int
547 macid_parse(p, ep)
548         char *p;
549         char **ep;
550 {
551         int mid;
552         char *bp;
553         char mbuf[MAXMACNAMELEN + 1];
554
555         if (tTd(35, 14))
556         {
557                 sm_dprintf("macid(");
558                 xputs(sm_debug_file(), p);
559                 sm_dprintf(") => ");
560         }
561
562         if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
563         {
564                 syserr("Name required for macro/class");
565                 if (ep != NULL)
566                         *ep = p;
567                 if (tTd(35, 14))
568                         sm_dprintf("NULL\n");
569                 return 0;
570         }
571         if (*p != '{')
572         {
573                 /* the macro is its own code */
574                 if (ep != NULL)
575                         *ep = p + 1;
576                 if (tTd(35, 14))
577                 {
578                         char buf[2];
579
580                         buf[0] = *p;
581                         buf[1] = '\0';
582                         xputs(sm_debug_file(), buf);
583                         sm_dprintf("\n");
584                 }
585                 return bitidx(*p);
586         }
587         bp = mbuf;
588         while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
589         {
590                 if (isascii(*p) && (isalnum(*p) || *p == '_'))
591                         *bp++ = *p;
592                 else
593                         syserr("Invalid macro/class character %c", *p);
594         }
595         *bp = '\0';
596         mid = -1;
597         if (*p == '\0')
598         {
599                 syserr("Unbalanced { on %s", mbuf);     /* missing } */
600         }
601         else if (*p != '}')
602         {
603                 syserr("Macro/class name ({%s}) too long (%d chars max)",
604                         mbuf, (int) (sizeof(mbuf) - 1));
605         }
606         else if (mbuf[1] == '\0')
607         {
608                 /* ${x} == $x */
609                 mid = bitidx(mbuf[0]);
610                 p++;
611         }
612         else
613         {
614                 STAB *s;
615
616                 s = stab(mbuf, ST_MACRO, ST_ENTER);
617                 if (s->s_macro != 0)
618                         mid = s->s_macro;
619                 else
620                 {
621                         if (NextMacroId > MAXMACROID)
622                         {
623                                 syserr("Macro/class {%s}: too many long names",
624                                         mbuf);
625                                 s->s_macro = -1;
626                         }
627                         else
628                         {
629                                 MacroName[NextMacroId] = s->s_name;
630                                 s->s_macro = mid = NextMacroId++;
631                         }
632                 }
633                 p++;
634         }
635         if (ep != NULL)
636                 *ep = p;
637         if (mid < 0 || mid > MAXMACROID)
638         {
639                 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
640                 if (tTd(35, 14))
641                         sm_dprintf("NULL\n");
642                 return 0;
643         }
644         if (tTd(35, 14))
645                 sm_dprintf("0x%x\n", mid);
646         return mid;
647 }
648
649 /*
650 **  WORDINCLASS -- tell if a word is in a specific class
651 **
652 **      Parameters:
653 **              str -- the name of the word to look up.
654 **              cl -- the class name.
655 **
656 **      Returns:
657 **              true if str can be found in cl.
658 **              false otherwise.
659 */
660
661 bool
662 wordinclass(str, cl)
663         char *str;
664         int cl;
665 {
666         STAB *s;
667
668         s = stab(str, ST_CLASS, ST_FIND);
669         return s != NULL && bitnset(bitidx(cl), s->s_class);
670 }