macro.c revision 95154
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 16SM_RCSID("@(#)$Id: macro.c,v 1.1.1.7 2002/02/17 21:56:39 gshapiro 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(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 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(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 368void 369macset(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 403char * 404macvalue(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 441char * 442macname(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 478int 479macid_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 585bool 586wordinclass(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} 595