macro.c revision 132943
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 16SM_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 22static char *MacroName[MAXMACROID + 1]; /* macro id to name table */ 23int 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 41struct 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 68void 69initmacros(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 113void 114expand(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 283void 284#if SM_HEAP_CHECK 285macdefine_tagged(mac, vclass, id, value, file, line, grp) 286#else /* SM_HEAP_CHECK */ 287macdefine(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 372void 373macset(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 407char * 408macvalue(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 445char * 446macname(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 482int 483macid_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 589bool 590wordinclass(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} 599