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