122707Sdist /* 222707Sdist ** Sendmail 322707Sdist ** Copyright (c) 1983 Eric P. Allman 422707Sdist ** Berkeley, California 522707Sdist ** 622707Sdist ** Copyright (c) 1983 Regents of the University of California. 722707Sdist ** All rights reserved. The Berkeley software License Agreement 822707Sdist ** specifies the terms and conditions for redistribution. 922707Sdist */ 1022707Sdist 1122707Sdist #ifndef lint 12*24941Seric static char SccsId[] = "@(#)macro.c 5.3 (Berkeley) 09/19/85"; 1322707Sdist #endif not lint 1422707Sdist 156056Seric # include "sendmail.h" 163379Seric 173379Seric /* 183379Seric ** EXPAND -- macro expand a string using $x escapes. 193379Seric ** 203379Seric ** Parameters: 213379Seric ** s -- the string to expand. 223379Seric ** buf -- the place to put the expansion. 233379Seric ** buflim -- the buffer limit, i.e., the address 243379Seric ** of the last usable position in buf. 256980Seric ** e -- envelope in which to work. 263379Seric ** 273379Seric ** Returns: 289382Seric ** none. 293379Seric ** 303379Seric ** Side Effects: 313379Seric ** none. 323379Seric */ 333379Seric 346980Seric expand(s, buf, buflim, e) 356980Seric register char *s; 366980Seric register char *buf; 376980Seric char *buflim; 386980Seric register ENVELOPE *e; 396980Seric { 4017349Seric register char *xp; 416056Seric register char *q; 429382Seric bool skipping; /* set if conditionally skipping output */ 4317349Seric bool recurse = FALSE; /* set if recursion required */ 4417349Seric int i; 456056Seric char xbuf[BUFSIZ]; 468182Seric extern char *macvalue(); 473379Seric 483379Seric # ifdef DEBUG 49*24941Seric if (tTd(35, 24)) 506056Seric { 516056Seric printf("expand("); 526056Seric xputs(s); 536056Seric printf(")\n"); 546056Seric } 553379Seric # endif DEBUG 563379Seric 573387Seric skipping = FALSE; 588064Seric if (s == NULL) 598064Seric s = ""; 6017349Seric for (xp = xbuf; *s != '\0'; s++) 613379Seric { 626056Seric char c; 634319Seric 644319Seric /* 656056Seric ** Check for non-ordinary (special?) character. 664319Seric ** 'q' will be the interpolated quantity. 674319Seric */ 684319Seric 693379Seric q = NULL; 706056Seric c = *s; 716056Seric switch (c) 723387Seric { 736056Seric case CONDIF: /* see if var set */ 743387Seric c = *++s; 758182Seric skipping = macvalue(c, e) == NULL; 766056Seric continue; 773387Seric 786056Seric case CONDELSE: /* change state of skipping */ 796056Seric skipping = !skipping; 806056Seric continue; 813387Seric 826056Seric case CONDFI: /* stop skipping */ 836056Seric skipping = FALSE; 846056Seric continue; 853387Seric 8616146Seric case '\001': /* macro interpolation */ 876056Seric c = *++s; 888182Seric q = macvalue(c & 0177, e); 899382Seric if (q == NULL) 903387Seric continue; 916056Seric break; 923387Seric } 933387Seric 943379Seric /* 953379Seric ** Interpolate q or output one character 963379Seric */ 973379Seric 9817349Seric if (skipping || xp >= &xbuf[sizeof xbuf]) 993387Seric continue; 10017349Seric if (q == NULL) 10117349Seric *xp++ = c; 10217349Seric else 1036056Seric { 10417349Seric /* copy to end of q or max space remaining in buf */ 10517349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 1066056Seric { 10717349Seric if (iscntrl(c) && !isspace(c)) 10817349Seric recurse = TRUE; 1096056Seric *xp++ = c; 1106056Seric } 1116056Seric } 1123379Seric } 1136056Seric *xp = '\0'; 1143379Seric 1153379Seric # ifdef DEBUG 116*24941Seric if (tTd(35, 24)) 1176056Seric { 1188064Seric printf("expand ==> "); 1196056Seric xputs(xbuf); 1208064Seric printf("\n"); 1216056Seric } 1223379Seric # endif DEBUG 1233379Seric 1246056Seric /* recurse as appropriate */ 12517349Seric if (recurse) 1269382Seric { 1279382Seric expand(xbuf, buf, buflim, e); 1289382Seric return; 1299382Seric } 1306056Seric 1316056Seric /* copy results out */ 13217349Seric i = buflim - buf - 1; 13317349Seric if (i > xp - xbuf) 13417349Seric i = xp - xbuf; 13517349Seric bcopy(xbuf, buf, i); 13617349Seric buf[i] = '\0'; 1373379Seric } 1383379Seric /* 1393379Seric ** DEFINE -- define a macro. 1403379Seric ** 1413379Seric ** this would be better done using a #define macro. 1423379Seric ** 1433379Seric ** Parameters: 1443379Seric ** n -- the macro name. 1453379Seric ** v -- the macro value. 1469382Seric ** e -- the envelope to store the definition in. 1473379Seric ** 1483379Seric ** Returns: 1493379Seric ** none. 1503379Seric ** 1513379Seric ** Side Effects: 1529382Seric ** e->e_macro[n] is defined. 1534092Seric ** 1544092Seric ** Notes: 1554092Seric ** There is one macro for each ASCII character, 1564092Seric ** although they are not all used. The currently 1574092Seric ** defined macros are: 1584092Seric ** 1594202Seric ** $a date in ARPANET format (preferring the Date: line 1604202Seric ** of the message) 1614202Seric ** $b the current date (as opposed to the date as found 1624202Seric ** the message) in ARPANET format 1634092Seric ** $c hop count 1644202Seric ** $d (current) date in UNIX (ctime) format 16510710Seric ** $e the SMTP entry message+ 1664092Seric ** $f raw from address 1674092Seric ** $g translated from address 1684092Seric ** $h to host 1697851Seric ** $i queue id 1707851Seric ** $j official SMTP hostname, used in messages+ 1714092Seric ** $l UNIX-style from line+ 1724092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1734092Seric ** net typically)+ 1744092Seric ** $o delimiters ("operators") for address tokens+ 1754092Seric ** $p my process id in decimal 1765919Seric ** $q the string that becomes an address -- this is 1775919Seric ** normally used to combine $g & $x. 1785187Seric ** $r protocol used to talk to sender 1795187Seric ** $s sender's host name 1804092Seric ** $t the current time in seconds since 1/1/1970 1814092Seric ** $u to user 1824092Seric ** $v version number of sendmail 18310407Seric ** $w our host name (if it can be determined) 1844092Seric ** $x signature (full name) of from person 1854202Seric ** $y the tty id of our terminal 1864092Seric ** $z home directory of to person 1874092Seric ** 1884092Seric ** Macros marked with + must be defined in the 1894092Seric ** configuration file and are used internally, but 1904092Seric ** are not set. 1914092Seric ** 1924092Seric ** There are also some macros that can be used 1934092Seric ** arbitrarily to make the configuration file 1944092Seric ** cleaner. In general all upper-case letters 1954092Seric ** are available. 1963379Seric */ 1973379Seric 1989382Seric define(n, v, e) 1993379Seric char n; 2003379Seric char *v; 2019382Seric register ENVELOPE *e; 2023379Seric { 2033379Seric # ifdef DEBUG 204*24941Seric if (tTd(35, 9)) 2056056Seric { 2066056Seric printf("define(%c as ", n); 2076056Seric xputs(v); 2086056Seric printf(")\n"); 2096056Seric } 2103379Seric # endif DEBUG 2119382Seric e->e_macro[n & 0177] = v; 2123379Seric } 2134454Seric /* 2144454Seric ** MACVALUE -- return uninterpreted value of a macro. 2154454Seric ** 2164454Seric ** Parameters: 2174454Seric ** n -- the name of the macro. 2184454Seric ** 2194454Seric ** Returns: 2204454Seric ** The value of n. 2214454Seric ** 2224454Seric ** Side Effects: 2234454Seric ** none. 2244454Seric */ 2254454Seric 2264454Seric char * 2278182Seric macvalue(n, e) 2284454Seric char n; 2298182Seric register ENVELOPE *e; 2304454Seric { 2318182Seric n &= 0177; 2328182Seric while (e != NULL) 2338182Seric { 2348182Seric register char *p = e->e_macro[n]; 2358182Seric 2368182Seric if (p != NULL) 2378182Seric return (p); 2388182Seric e = e->e_parent; 2398182Seric } 2408182Seric return (NULL); 2414454Seric } 242