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