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 #ifndef lint 15 static char id[] = "@(#)$Id: macro.c,v 8.40.16.9 2001/02/22 01:16:55 gshapiro Exp $"; 16 #endif /* ! lint */ 17 18 #include <sendmail.h> 19 20 #if MAXMACROID != (BITMAPBITS - 1) 21 ERROR Read the comment in conf.h 22 #endif /* MAXMACROID != (BITMAPBITS - 1) */ 23 24 char *MacroName[MAXMACROID + 1]; /* macro id to name table */ 25 int NextMacroId = 0240; /* codes for long named macros */ 26 27 /* 28 ** EXPAND -- macro expand a string using $x escapes. 29 ** 30 ** Parameters: 31 ** s -- the string to expand. 32 ** buf -- the place to put the expansion. 33 ** bufsize -- the size of the buffer. 34 ** e -- envelope in which to work. 35 ** 36 ** Returns: 37 ** none. 38 ** 39 ** Side Effects: 40 ** none. 41 */ 42 43 void 44 expand(s, buf, bufsize, e) 45 register char *s; 46 register char *buf; 47 size_t bufsize; 48 register ENVELOPE *e; 49 { 50 register char *xp; 51 register char *q; 52 bool skipping; /* set if conditionally skipping output */ 53 bool recurse = FALSE; /* set if recursion required */ 54 int i; 55 int skiplev; /* skipping nesting level */ 56 int iflev; /* if nesting level */ 57 char xbuf[MACBUFSIZE]; 58 static int explevel = 0; 59 60 if (tTd(35, 24)) 61 { 62 dprintf("expand("); 63 xputs(s); 64 dprintf(")\n"); 65 } 66 67 skipping = FALSE; 68 skiplev = 0; 69 iflev = 0; 70 if (s == NULL) 71 s = ""; 72 for (xp = xbuf; *s != '\0'; s++) 73 { 74 int c; 75 76 /* 77 ** Check for non-ordinary (special?) character. 78 ** 'q' will be the interpolated quantity. 79 */ 80 81 q = NULL; 82 c = *s; 83 switch (c & 0377) 84 { 85 case CONDIF: /* see if var set */ 86 iflev++; 87 c = *++s; 88 if (skipping) 89 skiplev++; 90 else 91 { 92 char *mv; 93 94 mv = macvalue(c, e); 95 skipping = (mv == NULL || *mv == '\0'); 96 } 97 continue; 98 99 case CONDELSE: /* change state of skipping */ 100 if (iflev == 0) 101 break; 102 if (skiplev == 0) 103 skipping = !skipping; 104 continue; 105 106 case CONDFI: /* stop skipping */ 107 if (iflev == 0) 108 break; 109 iflev--; 110 if (skiplev == 0) 111 skipping = FALSE; 112 if (skipping) 113 skiplev--; 114 continue; 115 116 case MACROEXPAND: /* macro interpolation */ 117 c = bitidx(*++s); 118 if (c != '\0') 119 q = macvalue(c, e); 120 else 121 { 122 s--; 123 q = NULL; 124 } 125 if (q == NULL) 126 continue; 127 break; 128 } 129 130 /* 131 ** Interpolate q or output one character 132 */ 133 134 if (skipping || xp >= &xbuf[sizeof xbuf - 1]) 135 continue; 136 if (q == NULL) 137 *xp++ = c; 138 else 139 { 140 /* copy to end of q or max space remaining in buf */ 141 while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 142 { 143 /* check for any sendmail metacharacters */ 144 if ((c & 0340) == 0200) 145 recurse = TRUE; 146 *xp++ = c; 147 } 148 } 149 } 150 *xp = '\0'; 151 152 if (tTd(35, 24)) 153 { 154 dprintf("expand ==> "); 155 xputs(xbuf); 156 dprintf("\n"); 157 } 158 159 /* recurse as appropriate */ 160 if (recurse) 161 { 162 if (explevel < MaxMacroRecursion) 163 { 164 explevel++; 165 expand(xbuf, buf, bufsize, e); 166 explevel--; 167 return; 168 } 169 syserr("expand: recursion too deep (%d max)", 170 MaxMacroRecursion); 171 } 172 173 /* copy results out */ 174 i = xp - xbuf; 175 if ((size_t)i >= bufsize) 176 i = bufsize - 1; 177 memmove(buf, xbuf, i); 178 buf[i] = '\0'; 179 } 180 /* 181 ** DEFINE -- define a macro. 182 ** 183 ** this would be better done using a #define macro. 184 ** 185 ** Parameters: 186 ** n -- the macro name. 187 ** v -- the macro value. 188 ** e -- the envelope to store the definition in. 189 ** 190 ** Returns: 191 ** none. 192 ** 193 ** Side Effects: 194 ** e->e_macro[n] is defined. 195 ** 196 ** Notes: 197 ** There is one macro for each ASCII character, 198 ** although they are not all used. The currently 199 ** defined macros are: 200 ** 201 ** $a date in ARPANET format (preferring the Date: line 202 ** of the message) 203 ** $b the current date (as opposed to the date as found 204 ** the message) in ARPANET format 205 ** $c hop count 206 ** $d (current) date in UNIX (ctime) format 207 ** $e the SMTP entry message+ 208 ** $f raw from address 209 ** $g translated from address 210 ** $h to host 211 ** $i queue id 212 ** $j official SMTP hostname, used in messages+ 213 ** $k UUCP node name 214 ** $l UNIX-style from line+ 215 ** $m The domain part of our full name. 216 ** $n name of sendmail ("MAILER-DAEMON" on local 217 ** net typically)+ 218 ** $o delimiters ("operators") for address tokens+ 219 ** (set via OperatorChars option in V6 or later 220 ** sendmail.cf files) 221 ** $p my process id in decimal 222 ** $q the string that becomes an address -- this is 223 ** normally used to combine $g & $x. 224 ** $r protocol used to talk to sender 225 ** $s sender's host name 226 ** $t the current time in seconds since 1/1/1970 227 ** $u to user 228 ** $v version number of sendmail 229 ** $w our host name (if it can be determined) 230 ** $x signature (full name) of from person 231 ** $y the tty id of our terminal 232 ** $z home directory of to person 233 ** $_ RFC1413 authenticated sender address 234 ** 235 ** Macros marked with + must be defined in the 236 ** configuration file and are used internally, but 237 ** are not set. 238 ** 239 ** There are also some macros that can be used 240 ** arbitrarily to make the configuration file 241 ** cleaner. In general all upper-case letters 242 ** are available. 243 */ 244 245 void 246 define(n, v, e) 247 int n; 248 char *v; 249 register ENVELOPE *e; 250 { 251 int m; 252 253 m = bitidx(n); 254 if (tTd(35, 9)) 255 { 256 dprintf("%sdefine(%s as ", 257 (e->e_macro[m] == NULL) ? "" 258 : "re", macname(n)); 259 xputs(v); 260 dprintf(")\n"); 261 } 262 e->e_macro[m] = v; 263 264 #if _FFR_RESET_MACRO_GLOBALS 265 switch (m) 266 { 267 case 'j': 268 MyHostName = v; 269 break; 270 } 271 #endif /* _FFR_RESET_MACRO_GLOBALS */ 272 } 273 /* 274 ** MACVALUE -- return uninterpreted value of a macro. 275 ** 276 ** Parameters: 277 ** n -- the name of the macro. 278 ** 279 ** Returns: 280 ** The value of n. 281 ** 282 ** Side Effects: 283 ** none. 284 */ 285 286 char * 287 macvalue(n, e) 288 int n; 289 register ENVELOPE *e; 290 { 291 n = bitidx(n); 292 while (e != NULL) 293 { 294 register char *p = e->e_macro[n]; 295 296 if (p != NULL) 297 return p; 298 if (e == e->e_parent) 299 break; 300 e = e->e_parent; 301 } 302 return NULL; 303 } 304 /* 305 ** MACNAME -- return the name of a macro given its internal id 306 ** 307 ** Parameter: 308 ** n -- the id of the macro 309 ** 310 ** Returns: 311 ** The name of n. 312 ** 313 ** Side Effects: 314 ** none. 315 */ 316 317 char * 318 macname(n) 319 int n; 320 { 321 static char mbuf[2]; 322 323 n = bitidx(n); 324 if (bitset(0200, n)) 325 { 326 char *p = MacroName[n]; 327 328 if (p != NULL) 329 return p; 330 return "***UNDEFINED MACRO***"; 331 } 332 mbuf[0] = n; 333 mbuf[1] = '\0'; 334 return mbuf; 335 } 336 /* 337 ** MACID -- return id of macro identified by its name 338 ** 339 ** Parameters: 340 ** p -- pointer to name string -- either a single 341 ** character or {name}. 342 ** ep -- filled in with the pointer to the byte 343 ** after the name. 344 ** 345 ** Returns: 346 ** The internal id code for this macro. This will 347 ** fit into a single byte. 348 ** 349 ** Side Effects: 350 ** If this is a new macro name, a new id is allocated. 351 */ 352 353 int 354 macid(p, ep) 355 register char *p; 356 char **ep; 357 { 358 int mid; 359 register char *bp; 360 char mbuf[MAXMACNAMELEN + 1]; 361 362 if (tTd(35, 14)) 363 { 364 dprintf("macid("); 365 xputs(p); 366 dprintf(") => "); 367 } 368 369 if (*p == '\0' || (p[0] == '{' && p[1] == '}')) 370 { 371 syserr("Name required for macro/class"); 372 if (ep != NULL) 373 *ep = p; 374 if (tTd(35, 14)) 375 dprintf("NULL\n"); 376 return 0; 377 } 378 if (*p != '{') 379 { 380 /* the macro is its own code */ 381 if (ep != NULL) 382 *ep = p + 1; 383 if (tTd(35, 14)) 384 dprintf("%c\n", bitidx(*p)); 385 return bitidx(*p); 386 } 387 bp = mbuf; 388 while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1]) 389 { 390 if (isascii(*p) && (isalnum(*p) || *p == '_')) 391 *bp++ = *p; 392 else 393 syserr("Invalid macro/class character %c", *p); 394 } 395 *bp = '\0'; 396 mid = -1; 397 if (*p == '\0') 398 { 399 syserr("Unbalanced { on %s", mbuf); /* missing } */ 400 } 401 else if (*p != '}') 402 { 403 syserr("Macro/class name ({%s}) too long (%d chars max)", 404 mbuf, sizeof mbuf - 1); 405 } 406 else if (mbuf[1] == '\0') 407 { 408 /* ${x} == $x */ 409 mid = bitidx(mbuf[0]); 410 p++; 411 } 412 else 413 { 414 register STAB *s; 415 416 s = stab(mbuf, ST_MACRO, ST_ENTER); 417 if (s->s_macro != 0) 418 mid = s->s_macro; 419 else 420 { 421 if (NextMacroId > MAXMACROID) 422 { 423 syserr("Macro/class {%s}: too many long names", mbuf); 424 s->s_macro = -1; 425 } 426 else 427 { 428 MacroName[NextMacroId] = s->s_name; 429 s->s_macro = mid = NextMacroId++; 430 } 431 } 432 p++; 433 } 434 if (ep != NULL) 435 *ep = p; 436 if (mid < 0 || mid > MAXMACROID) 437 { 438 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid); 439 if (tTd(35, 14)) 440 dprintf("NULL\n"); 441 return 0; 442 } 443 if (tTd(35, 14)) 444 dprintf("0x%x\n", mid); 445 return mid; 446 } 447 /* 448 ** WORDINCLASS -- tell if a word is in a specific class 449 ** 450 ** Parameters: 451 ** str -- the name of the word to look up. 452 ** cl -- the class name. 453 ** 454 ** Returns: 455 ** TRUE if str can be found in cl. 456 ** FALSE otherwise. 457 */ 458 459 bool 460 wordinclass(str, cl) 461 char *str; 462 int cl; 463 { 464 register STAB *s; 465 466 s = stab(str, ST_CLASS, ST_FIND); 467 return s != NULL && bitnset(bitidx(cl), s->s_class); 468 } 469