122707Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 362525Sbostic * Copyright (c) 1988, 1993 462525Sbostic * The Regents of the University of California. All rights reserved. 533729Sbostic * 642826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822707Sdist 922707Sdist #ifndef lint 10*66019Seric static char sccsid[] = "@(#)macro.c 8.3 (Berkeley) 02/07/94"; 1133729Sbostic #endif /* not lint */ 1222707Sdist 136056Seric # include "sendmail.h" 143379Seric 153379Seric /* 163379Seric ** EXPAND -- macro expand a string using $x escapes. 173379Seric ** 183379Seric ** Parameters: 193379Seric ** s -- the string to expand. 203379Seric ** buf -- the place to put the expansion. 213379Seric ** buflim -- the buffer limit, i.e., the address 223379Seric ** of the last usable position in buf. 236980Seric ** e -- envelope in which to work. 243379Seric ** 253379Seric ** Returns: 269382Seric ** none. 273379Seric ** 283379Seric ** Side Effects: 293379Seric ** none. 303379Seric */ 313379Seric 3260494Seric void 336980Seric expand(s, buf, buflim, e) 346980Seric register char *s; 356980Seric register char *buf; 366980Seric char *buflim; 376980Seric register ENVELOPE *e; 386980Seric { 3917349Seric register char *xp; 406056Seric register char *q; 419382Seric bool skipping; /* set if conditionally skipping output */ 4217349Seric bool recurse = FALSE; /* set if recursion required */ 4317349Seric int i; 4457589Seric int iflev; /* if nesting level */ 456056Seric char xbuf[BUFSIZ]; 463379Seric 4724941Seric if (tTd(35, 24)) 486056Seric { 496056Seric printf("expand("); 506056Seric xputs(s); 516056Seric printf(")\n"); 526056Seric } 533379Seric 543387Seric skipping = FALSE; 5557589Seric iflev = 0; 568064Seric if (s == NULL) 578064Seric s = ""; 5817349Seric for (xp = xbuf; *s != '\0'; s++) 593379Seric { 6064087Seric int c; 614319Seric 624319Seric /* 636056Seric ** Check for non-ordinary (special?) character. 644319Seric ** 'q' will be the interpolated quantity. 654319Seric */ 664319Seric 673379Seric q = NULL; 686056Seric c = *s; 6958050Seric switch (c & 0377) 703387Seric { 716056Seric case CONDIF: /* see if var set */ 7257977Seric c = *++s; 7357977Seric if (skipping) 7457977Seric iflev++; 7557977Seric else 7657589Seric skipping = macvalue(c, e) == NULL; 7757977Seric continue; 783387Seric 796056Seric case CONDELSE: /* change state of skipping */ 8057977Seric if (iflev == 0) 8157589Seric skipping = !skipping; 826056Seric continue; 833387Seric 846056Seric case CONDFI: /* stop skipping */ 8557977Seric if (iflev == 0) 8657589Seric skipping = FALSE; 8757977Seric if (skipping) 8857977Seric iflev--; 8957977Seric continue; 903387Seric 9158050Seric case MACROEXPAND: /* macro interpolation */ 92*66019Seric c = *++s & 0177; 93*66019Seric if (c != '\0') 94*66019Seric q = macvalue(c, e); 95*66019Seric else 96*66019Seric { 97*66019Seric s--; 98*66019Seric q = NULL; 99*66019Seric } 1009382Seric if (q == NULL) 1013387Seric continue; 1026056Seric break; 1033387Seric } 1043387Seric 1053379Seric /* 1063379Seric ** Interpolate q or output one character 1073379Seric */ 1083379Seric 10917349Seric if (skipping || xp >= &xbuf[sizeof xbuf]) 1103387Seric continue; 11117349Seric if (q == NULL) 11217349Seric *xp++ = c; 11317349Seric else 1146056Seric { 11517349Seric /* copy to end of q or max space remaining in buf */ 11617349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 1176056Seric { 11858050Seric /* check for any sendmail metacharacters */ 11958050Seric if ((c & 0340) == 0200) 12017349Seric recurse = TRUE; 1216056Seric *xp++ = c; 1226056Seric } 1236056Seric } 1243379Seric } 1256056Seric *xp = '\0'; 1263379Seric 12724941Seric if (tTd(35, 24)) 1286056Seric { 1298064Seric printf("expand ==> "); 1306056Seric xputs(xbuf); 1318064Seric printf("\n"); 1326056Seric } 1333379Seric 1346056Seric /* recurse as appropriate */ 13517349Seric if (recurse) 1369382Seric { 1379382Seric expand(xbuf, buf, buflim, e); 1389382Seric return; 1399382Seric } 1406056Seric 1416056Seric /* copy results out */ 14217349Seric i = buflim - buf - 1; 14317349Seric if (i > xp - xbuf) 14417349Seric i = xp - xbuf; 14517349Seric bcopy(xbuf, buf, i); 14617349Seric buf[i] = '\0'; 1473379Seric } 1483379Seric /* 1493379Seric ** DEFINE -- define a macro. 1503379Seric ** 1513379Seric ** this would be better done using a #define macro. 1523379Seric ** 1533379Seric ** Parameters: 1543379Seric ** n -- the macro name. 1553379Seric ** v -- the macro value. 1569382Seric ** e -- the envelope to store the definition in. 1573379Seric ** 1583379Seric ** Returns: 1593379Seric ** none. 1603379Seric ** 1613379Seric ** Side Effects: 1629382Seric ** e->e_macro[n] is defined. 1634092Seric ** 1644092Seric ** Notes: 1654092Seric ** There is one macro for each ASCII character, 1664092Seric ** although they are not all used. The currently 1674092Seric ** defined macros are: 1684092Seric ** 1694202Seric ** $a date in ARPANET format (preferring the Date: line 1704202Seric ** of the message) 1714202Seric ** $b the current date (as opposed to the date as found 1724202Seric ** the message) in ARPANET format 1734092Seric ** $c hop count 1744202Seric ** $d (current) date in UNIX (ctime) format 17510710Seric ** $e the SMTP entry message+ 1764092Seric ** $f raw from address 1774092Seric ** $g translated from address 1784092Seric ** $h to host 1797851Seric ** $i queue id 1807851Seric ** $j official SMTP hostname, used in messages+ 18157630Seric ** $k UUCP node name 1824092Seric ** $l UNIX-style from line+ 18358319Seric ** $m The domain part of our full name. 1844092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1854092Seric ** net typically)+ 1864092Seric ** $o delimiters ("operators") for address tokens+ 1874092Seric ** $p my process id in decimal 1885919Seric ** $q the string that becomes an address -- this is 1895919Seric ** normally used to combine $g & $x. 1905187Seric ** $r protocol used to talk to sender 1915187Seric ** $s sender's host name 1924092Seric ** $t the current time in seconds since 1/1/1970 1934092Seric ** $u to user 1944092Seric ** $v version number of sendmail 19510407Seric ** $w our host name (if it can be determined) 1964092Seric ** $x signature (full name) of from person 1974202Seric ** $y the tty id of our terminal 1984092Seric ** $z home directory of to person 19958951Seric ** $_ RFC1413 authenticated sender address 2004092Seric ** 2014092Seric ** Macros marked with + must be defined in the 2024092Seric ** configuration file and are used internally, but 2034092Seric ** are not set. 2044092Seric ** 2054092Seric ** There are also some macros that can be used 2064092Seric ** arbitrarily to make the configuration file 2074092Seric ** cleaner. In general all upper-case letters 2084092Seric ** are available. 2093379Seric */ 2103379Seric 21160494Seric void 2129382Seric define(n, v, e) 21364087Seric int n; 2143379Seric char *v; 2159382Seric register ENVELOPE *e; 2163379Seric { 21724941Seric if (tTd(35, 9)) 2186056Seric { 2196056Seric printf("define(%c as ", n); 2206056Seric xputs(v); 2216056Seric printf(")\n"); 2226056Seric } 2239382Seric e->e_macro[n & 0177] = v; 2243379Seric } 2254454Seric /* 2264454Seric ** MACVALUE -- return uninterpreted value of a macro. 2274454Seric ** 2284454Seric ** Parameters: 2294454Seric ** n -- the name of the macro. 2304454Seric ** 2314454Seric ** Returns: 2324454Seric ** The value of n. 2334454Seric ** 2344454Seric ** Side Effects: 2354454Seric ** none. 2364454Seric */ 2374454Seric 2384454Seric char * 2398182Seric macvalue(n, e) 24064087Seric int n; 2418182Seric register ENVELOPE *e; 2424454Seric { 2438182Seric n &= 0177; 2448182Seric while (e != NULL) 2458182Seric { 2468182Seric register char *p = e->e_macro[n]; 2478182Seric 2488182Seric if (p != NULL) 2498182Seric return (p); 2508182Seric e = e->e_parent; 2518182Seric } 2528182Seric return (NULL); 2534454Seric } 254