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 } 599