122707Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333729Sbostic * Copyright (c) 1988 Regents of the University of California. 433729Sbostic * All rights reserved. 533729Sbostic * 642826Sbostic * %sccs.include.redist.c% 733729Sbostic */ 822707Sdist 922707Sdist #ifndef lint 10*57630Seric static char sccsid[] = "@(#)macro.c 6.3 (Berkeley) 01/20/93"; 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 326980Seric expand(s, buf, buflim, e) 336980Seric register char *s; 346980Seric register char *buf; 356980Seric char *buflim; 366980Seric register ENVELOPE *e; 376980Seric { 3817349Seric register char *xp; 396056Seric register char *q; 409382Seric bool skipping; /* set if conditionally skipping output */ 4117349Seric bool recurse = FALSE; /* set if recursion required */ 4217349Seric int i; 4357589Seric int iflev; /* if nesting level */ 446056Seric char xbuf[BUFSIZ]; 458182Seric extern char *macvalue(); 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 { 606056Seric char 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; 696056Seric switch (c) 703387Seric { 716056Seric case CONDIF: /* see if var set */ 7257589Seric if (iflev++ <= 0) 7357589Seric { 7457589Seric c = *++s; 7557589Seric skipping = macvalue(c, e) == NULL; 7657589Seric continue; 7757589Seric } 7857589Seric break; 793387Seric 806056Seric case CONDELSE: /* change state of skipping */ 8157589Seric if (iflev == 1) 8257589Seric skipping = !skipping; 836056Seric continue; 843387Seric 856056Seric case CONDFI: /* stop skipping */ 8657589Seric if (--iflev <= 0) 8757589Seric { 8857589Seric skipping = FALSE; 8957589Seric continue; 9057589Seric } 9157589Seric break; 923387Seric 9316146Seric case '\001': /* macro interpolation */ 946056Seric c = *++s; 958182Seric q = macvalue(c & 0177, e); 969382Seric if (q == NULL) 973387Seric continue; 986056Seric break; 993387Seric } 1003387Seric 1013379Seric /* 1023379Seric ** Interpolate q or output one character 1033379Seric */ 1043379Seric 10517349Seric if (skipping || xp >= &xbuf[sizeof xbuf]) 1063387Seric continue; 10717349Seric if (q == NULL) 10817349Seric *xp++ = c; 10917349Seric else 1106056Seric { 11117349Seric /* copy to end of q or max space remaining in buf */ 11217349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 1136056Seric { 11417349Seric if (iscntrl(c) && !isspace(c)) 11517349Seric recurse = TRUE; 1166056Seric *xp++ = c; 1176056Seric } 1186056Seric } 1193379Seric } 1206056Seric *xp = '\0'; 1213379Seric 12224941Seric if (tTd(35, 24)) 1236056Seric { 1248064Seric printf("expand ==> "); 1256056Seric xputs(xbuf); 1268064Seric printf("\n"); 1276056Seric } 1283379Seric 1296056Seric /* recurse as appropriate */ 13017349Seric if (recurse) 1319382Seric { 1329382Seric expand(xbuf, buf, buflim, e); 1339382Seric return; 1349382Seric } 1356056Seric 1366056Seric /* copy results out */ 13717349Seric i = buflim - buf - 1; 13817349Seric if (i > xp - xbuf) 13917349Seric i = xp - xbuf; 14017349Seric bcopy(xbuf, buf, i); 14117349Seric buf[i] = '\0'; 1423379Seric } 1433379Seric /* 1443379Seric ** DEFINE -- define a macro. 1453379Seric ** 1463379Seric ** this would be better done using a #define macro. 1473379Seric ** 1483379Seric ** Parameters: 1493379Seric ** n -- the macro name. 1503379Seric ** v -- the macro value. 1519382Seric ** e -- the envelope to store the definition in. 1523379Seric ** 1533379Seric ** Returns: 1543379Seric ** none. 1553379Seric ** 1563379Seric ** Side Effects: 1579382Seric ** e->e_macro[n] is defined. 1584092Seric ** 1594092Seric ** Notes: 1604092Seric ** There is one macro for each ASCII character, 1614092Seric ** although they are not all used. The currently 1624092Seric ** defined macros are: 1634092Seric ** 1644202Seric ** $a date in ARPANET format (preferring the Date: line 1654202Seric ** of the message) 1664202Seric ** $b the current date (as opposed to the date as found 1674202Seric ** the message) in ARPANET format 1684092Seric ** $c hop count 1694202Seric ** $d (current) date in UNIX (ctime) format 17010710Seric ** $e the SMTP entry message+ 1714092Seric ** $f raw from address 1724092Seric ** $g translated from address 1734092Seric ** $h to host 1747851Seric ** $i queue id 1757851Seric ** $j official SMTP hostname, used in messages+ 176*57630Seric ** $k UUCP node name 1774092Seric ** $l UNIX-style from line+ 1784092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1794092Seric ** net typically)+ 1804092Seric ** $o delimiters ("operators") for address tokens+ 1814092Seric ** $p my process id in decimal 1825919Seric ** $q the string that becomes an address -- this is 1835919Seric ** normally used to combine $g & $x. 1845187Seric ** $r protocol used to talk to sender 1855187Seric ** $s sender's host name 1864092Seric ** $t the current time in seconds since 1/1/1970 1874092Seric ** $u to user 1884092Seric ** $v version number of sendmail 18910407Seric ** $w our host name (if it can be determined) 1904092Seric ** $x signature (full name) of from person 1914202Seric ** $y the tty id of our terminal 1924092Seric ** $z home directory of to person 193*57630Seric ** $< the return path (sender in envelope) relative to recipient 1944092Seric ** 1954092Seric ** Macros marked with + must be defined in the 1964092Seric ** configuration file and are used internally, but 1974092Seric ** are not set. 1984092Seric ** 1994092Seric ** There are also some macros that can be used 2004092Seric ** arbitrarily to make the configuration file 2014092Seric ** cleaner. In general all upper-case letters 2024092Seric ** are available. 2033379Seric */ 2043379Seric 2059382Seric define(n, v, e) 2063379Seric char n; 2073379Seric char *v; 2089382Seric register ENVELOPE *e; 2093379Seric { 21024941Seric if (tTd(35, 9)) 2116056Seric { 2126056Seric printf("define(%c as ", n); 2136056Seric xputs(v); 2146056Seric printf(")\n"); 2156056Seric } 2169382Seric e->e_macro[n & 0177] = v; 2173379Seric } 2184454Seric /* 2194454Seric ** MACVALUE -- return uninterpreted value of a macro. 2204454Seric ** 2214454Seric ** Parameters: 2224454Seric ** n -- the name of the macro. 2234454Seric ** 2244454Seric ** Returns: 2254454Seric ** The value of n. 2264454Seric ** 2274454Seric ** Side Effects: 2284454Seric ** none. 2294454Seric */ 2304454Seric 2314454Seric char * 2328182Seric macvalue(n, e) 2334454Seric char n; 2348182Seric register ENVELOPE *e; 2354454Seric { 2368182Seric n &= 0177; 2378182Seric while (e != NULL) 2388182Seric { 2398182Seric register char *p = e->e_macro[n]; 2408182Seric 2418182Seric if (p != NULL) 2428182Seric return (p); 2438182Seric e = e->e_parent; 2448182Seric } 2458182Seric return (NULL); 2464454Seric } 247