1*22707Sdist /* 2*22707Sdist ** Sendmail 3*22707Sdist ** Copyright (c) 1983 Eric P. Allman 4*22707Sdist ** Berkeley, California 5*22707Sdist ** 6*22707Sdist ** Copyright (c) 1983 Regents of the University of California. 7*22707Sdist ** All rights reserved. The Berkeley software License Agreement 8*22707Sdist ** specifies the terms and conditions for redistribution. 9*22707Sdist */ 10*22707Sdist 11*22707Sdist #ifndef lint 12*22707Sdist static char SccsId[] = "@(#)macro.c 5.1 (Berkeley) 06/07/85"; 13*22707Sdist #endif not lint 14*22707Sdist 156056Seric # include "sendmail.h" 163379Seric 17*22707Sdist SCCSID(@(#)macro.c 5.1 06/07/85); 183379Seric 193379Seric /* 203379Seric ** EXPAND -- macro expand a string using $x escapes. 213379Seric ** 223379Seric ** Parameters: 233379Seric ** s -- the string to expand. 243379Seric ** buf -- the place to put the expansion. 253379Seric ** buflim -- the buffer limit, i.e., the address 263379Seric ** of the last usable position in buf. 276980Seric ** e -- envelope in which to work. 283379Seric ** 293379Seric ** Returns: 309382Seric ** none. 313379Seric ** 323379Seric ** Side Effects: 333379Seric ** none. 343379Seric */ 353379Seric 366980Seric expand(s, buf, buflim, e) 376980Seric register char *s; 386980Seric register char *buf; 396980Seric char *buflim; 406980Seric register ENVELOPE *e; 416980Seric { 4217349Seric register char *xp; 436056Seric register char *q; 449382Seric bool skipping; /* set if conditionally skipping output */ 4517349Seric bool recurse = FALSE; /* set if recursion required */ 4617349Seric int i; 476056Seric char xbuf[BUFSIZ]; 488182Seric extern char *macvalue(); 493379Seric 503379Seric # ifdef DEBUG 517677Seric if (tTd(35, 4)) 526056Seric { 536056Seric printf("expand("); 546056Seric xputs(s); 556056Seric printf(")\n"); 566056Seric } 573379Seric # endif DEBUG 583379Seric 593387Seric skipping = FALSE; 608064Seric if (s == NULL) 618064Seric s = ""; 6217349Seric for (xp = xbuf; *s != '\0'; s++) 633379Seric { 646056Seric char c; 654319Seric 664319Seric /* 676056Seric ** Check for non-ordinary (special?) character. 684319Seric ** 'q' will be the interpolated quantity. 694319Seric */ 704319Seric 713379Seric q = NULL; 726056Seric c = *s; 736056Seric switch (c) 743387Seric { 756056Seric case CONDIF: /* see if var set */ 763387Seric c = *++s; 778182Seric skipping = macvalue(c, e) == NULL; 786056Seric continue; 793387Seric 806056Seric case CONDELSE: /* change state of skipping */ 816056Seric skipping = !skipping; 826056Seric continue; 833387Seric 846056Seric case CONDFI: /* stop skipping */ 856056Seric skipping = FALSE; 866056Seric continue; 873387Seric 8816146Seric case '\001': /* macro interpolation */ 896056Seric c = *++s; 908182Seric q = macvalue(c & 0177, e); 919382Seric if (q == NULL) 923387Seric continue; 936056Seric break; 943387Seric } 953387Seric 963379Seric /* 973379Seric ** Interpolate q or output one character 983379Seric */ 993379Seric 10017349Seric if (skipping || xp >= &xbuf[sizeof xbuf]) 1013387Seric continue; 10217349Seric if (q == NULL) 10317349Seric *xp++ = c; 10417349Seric else 1056056Seric { 10617349Seric /* copy to end of q or max space remaining in buf */ 10717349Seric while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 1086056Seric { 10917349Seric if (iscntrl(c) && !isspace(c)) 11017349Seric recurse = TRUE; 1116056Seric *xp++ = c; 1126056Seric } 1136056Seric } 1143379Seric } 1156056Seric *xp = '\0'; 1163379Seric 1173379Seric # ifdef DEBUG 1187677Seric if (tTd(35, 4)) 1196056Seric { 1208064Seric printf("expand ==> "); 1216056Seric xputs(xbuf); 1228064Seric printf("\n"); 1236056Seric } 1243379Seric # endif DEBUG 1253379Seric 1266056Seric /* recurse as appropriate */ 12717349Seric if (recurse) 1289382Seric { 1299382Seric expand(xbuf, buf, buflim, e); 1309382Seric return; 1319382Seric } 1326056Seric 1336056Seric /* copy results out */ 13417349Seric i = buflim - buf - 1; 13517349Seric if (i > xp - xbuf) 13617349Seric i = xp - xbuf; 13717349Seric bcopy(xbuf, buf, i); 13817349Seric buf[i] = '\0'; 1393379Seric } 1403379Seric /* 1413379Seric ** DEFINE -- define a macro. 1423379Seric ** 1433379Seric ** this would be better done using a #define macro. 1443379Seric ** 1453379Seric ** Parameters: 1463379Seric ** n -- the macro name. 1473379Seric ** v -- the macro value. 1489382Seric ** e -- the envelope to store the definition in. 1493379Seric ** 1503379Seric ** Returns: 1513379Seric ** none. 1523379Seric ** 1533379Seric ** Side Effects: 1549382Seric ** e->e_macro[n] is defined. 1554092Seric ** 1564092Seric ** Notes: 1574092Seric ** There is one macro for each ASCII character, 1584092Seric ** although they are not all used. The currently 1594092Seric ** defined macros are: 1604092Seric ** 1614202Seric ** $a date in ARPANET format (preferring the Date: line 1624202Seric ** of the message) 1634202Seric ** $b the current date (as opposed to the date as found 1644202Seric ** the message) in ARPANET format 1654092Seric ** $c hop count 1664202Seric ** $d (current) date in UNIX (ctime) format 16710710Seric ** $e the SMTP entry message+ 1684092Seric ** $f raw from address 1694092Seric ** $g translated from address 1704092Seric ** $h to host 1717851Seric ** $i queue id 1727851Seric ** $j official SMTP hostname, used in messages+ 1734092Seric ** $l UNIX-style from line+ 1744092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1754092Seric ** net typically)+ 1764092Seric ** $o delimiters ("operators") for address tokens+ 1774092Seric ** $p my process id in decimal 1785919Seric ** $q the string that becomes an address -- this is 1795919Seric ** normally used to combine $g & $x. 1805187Seric ** $r protocol used to talk to sender 1815187Seric ** $s sender's host name 1824092Seric ** $t the current time in seconds since 1/1/1970 1834092Seric ** $u to user 1844092Seric ** $v version number of sendmail 18510407Seric ** $w our host name (if it can be determined) 1864092Seric ** $x signature (full name) of from person 1874202Seric ** $y the tty id of our terminal 1884092Seric ** $z home directory of to person 1894092Seric ** 1904092Seric ** Macros marked with + must be defined in the 1914092Seric ** configuration file and are used internally, but 1924092Seric ** are not set. 1934092Seric ** 1944092Seric ** There are also some macros that can be used 1954092Seric ** arbitrarily to make the configuration file 1964092Seric ** cleaner. In general all upper-case letters 1974092Seric ** are available. 1983379Seric */ 1993379Seric 2009382Seric define(n, v, e) 2013379Seric char n; 2023379Seric char *v; 2039382Seric register ENVELOPE *e; 2043379Seric { 2053379Seric # ifdef DEBUG 2067677Seric if (tTd(35, 3)) 2076056Seric { 2086056Seric printf("define(%c as ", n); 2096056Seric xputs(v); 2106056Seric printf(")\n"); 2116056Seric } 2123379Seric # endif DEBUG 2139382Seric e->e_macro[n & 0177] = v; 2143379Seric } 2154454Seric /* 2164454Seric ** MACVALUE -- return uninterpreted value of a macro. 2174454Seric ** 2184454Seric ** Parameters: 2194454Seric ** n -- the name of the macro. 2204454Seric ** 2214454Seric ** Returns: 2224454Seric ** The value of n. 2234454Seric ** 2244454Seric ** Side Effects: 2254454Seric ** none. 2264454Seric */ 2274454Seric 2284454Seric char * 2298182Seric macvalue(n, e) 2304454Seric char n; 2318182Seric register ENVELOPE *e; 2324454Seric { 2338182Seric n &= 0177; 2348182Seric while (e != NULL) 2358182Seric { 2368182Seric register char *p = e->e_macro[n]; 2378182Seric 2388182Seric if (p != NULL) 2398182Seric return (p); 2408182Seric e = e->e_parent; 2418182Seric } 2428182Seric return (NULL); 2434454Seric } 244