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 16 SM_RCSID("@(#)$Id: macro.c,v 8.86 2001/09/11 04:05:14 gshapiro 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(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 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(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 368 void 369 macset(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 403 char * 404 macvalue(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 441 char * 442 macname(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 478 int 479 macid_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 585 bool 586 wordinclass(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