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