16056Seric # include "sendmail.h" 23379Seric 3*8182Seric SCCSID(@(#)macro.c 3.17 09/12/82); 43379Seric 53379Seric /* 63379Seric ** EXPAND -- macro expand a string using $x escapes. 73379Seric ** 83379Seric ** Parameters: 93379Seric ** s -- the string to expand. 103379Seric ** buf -- the place to put the expansion. 113379Seric ** buflim -- the buffer limit, i.e., the address 123379Seric ** of the last usable position in buf. 136980Seric ** e -- envelope in which to work. 143379Seric ** 153379Seric ** Returns: 164319Seric ** End of interpolated output. 173379Seric ** 183379Seric ** Side Effects: 193379Seric ** none. 203379Seric */ 213379Seric 226980Seric expand(s, buf, buflim, e) 236980Seric register char *s; 246980Seric register char *buf; 256980Seric char *buflim; 266980Seric register ENVELOPE *e; 276980Seric { 286980Seric extern char *expand2(); 296980Seric 306980Seric (void) expand2(s, buf, buflim, e); 316980Seric } 326980Seric 336980Seric 343379Seric char * 356980Seric expand2(s, buf, buflim, e) 363379Seric register char *s; 373379Seric register char *buf; 383379Seric char *buflim; 396980Seric register ENVELOPE *e; 403379Seric { 416056Seric register char *q; 426056Seric char xbuf[BUFSIZ]; 436056Seric register char *xp = xbuf; 444319Seric bool skipping; /* set if conditionally skipping output */ 456056Seric bool gotone = FALSE; /* set if any expansion done */ 46*8182Seric extern char *macvalue(); 473379Seric 483379Seric # ifdef DEBUG 497677Seric if (tTd(35, 4)) 506056Seric { 516056Seric printf("expand("); 526056Seric xputs(s); 536056Seric printf(")\n"); 546056Seric } 553379Seric # endif DEBUG 563379Seric 573387Seric skipping = FALSE; 588064Seric if (s == NULL) 598064Seric s = ""; 606056Seric for (; *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; 75*8182Seric 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 866056Seric case '$': /* macro interpolation */ 876056Seric c = *++s; 88*8182Seric q = macvalue(c & 0177, e); 894172Seric if (q == NULL && c != '$') 903387Seric continue; 916056Seric gotone = TRUE; 926056Seric break; 933387Seric } 943387Seric 953379Seric /* 963379Seric ** Interpolate q or output one character 973379Seric */ 983379Seric 993387Seric if (skipping) 1003387Seric continue; 1016056Seric while (xp < &xbuf[sizeof xbuf]) 1026056Seric { 1036056Seric if (q == NULL) 1046056Seric { 1056056Seric *xp++ = c; 1066056Seric break; 1076056Seric } 1086056Seric if (*q == NULL) 1096056Seric break; 1106056Seric *xp++ = *q++; 1116056Seric } 1123379Seric } 1136056Seric *xp = '\0'; 1143379Seric 1153379Seric # ifdef DEBUG 1167677Seric if (tTd(35, 4)) 1176056Seric { 1188064Seric printf("expand ==> "); 1196056Seric xputs(xbuf); 1208064Seric printf("\n"); 1216056Seric } 1223379Seric # endif DEBUG 1233379Seric 1246056Seric /* recurse as appropriate */ 1256056Seric if (gotone) 1266980Seric return (expand2(xbuf, buf, buflim, e)); 1276056Seric 1286056Seric /* copy results out */ 1296056Seric for (q = buf, xp = xbuf; xp != '\0' && q < buflim-1; ) 1306056Seric *q++ = *xp++; 1316056Seric *q = '\0'; 1326056Seric 1336056Seric return (q); 1343379Seric } 1353379Seric /* 1363379Seric ** DEFINE -- define a macro. 1373379Seric ** 1383379Seric ** this would be better done using a #define macro. 1393379Seric ** 1403379Seric ** Parameters: 1413379Seric ** n -- the macro name. 1423379Seric ** v -- the macro value. 1433379Seric ** 1443379Seric ** Returns: 1453379Seric ** none. 1463379Seric ** 1473379Seric ** Side Effects: 1486980Seric ** CurEnv->e_macro[n] is defined. 1494092Seric ** 1504092Seric ** Notes: 1514092Seric ** There is one macro for each ASCII character, 1524092Seric ** although they are not all used. The currently 1534092Seric ** defined macros are: 1544092Seric ** 1554202Seric ** $a date in ARPANET format (preferring the Date: line 1564202Seric ** of the message) 1574202Seric ** $b the current date (as opposed to the date as found 1584202Seric ** the message) in ARPANET format 1594092Seric ** $c hop count 1604202Seric ** $d (current) date in UNIX (ctime) format 1614092Seric ** $f raw from address 1624092Seric ** $g translated from address 1634092Seric ** $h to host 1647851Seric ** $i queue id 1657851Seric ** $j official SMTP hostname, used in messages+ 1664092Seric ** $l UNIX-style from line+ 1674092Seric ** $n name of sendmail ("MAILER-DAEMON" on local 1684092Seric ** net typically)+ 1694092Seric ** $o delimiters ("operators") for address tokens+ 1704092Seric ** $p my process id in decimal 1715919Seric ** $q the string that becomes an address -- this is 1725919Seric ** normally used to combine $g & $x. 1735187Seric ** $r protocol used to talk to sender 1745187Seric ** $s sender's host name 1754092Seric ** $t the current time in seconds since 1/1/1970 1764092Seric ** $u to user 1774092Seric ** $v version number of sendmail 1784092Seric ** $x signature (full name) of from person 1794202Seric ** $y the tty id of our terminal 1804092Seric ** $z home directory of to person 1814092Seric ** 1824092Seric ** Macros marked with + must be defined in the 1834092Seric ** configuration file and are used internally, but 1844092Seric ** are not set. 1854092Seric ** 1864092Seric ** There are also some macros that can be used 1874092Seric ** arbitrarily to make the configuration file 1884092Seric ** cleaner. In general all upper-case letters 1894092Seric ** are available. 1903379Seric */ 1913379Seric 1923379Seric define(n, v) 1933379Seric char n; 1943379Seric char *v; 1953379Seric { 1963379Seric # ifdef DEBUG 1977677Seric if (tTd(35, 3)) 1986056Seric { 1996056Seric printf("define(%c as ", n); 2006056Seric xputs(v); 2016056Seric printf(")\n"); 2026056Seric } 2033379Seric # endif DEBUG 2046980Seric CurEnv->e_macro[n & 0177] = v; 2053379Seric } 2064454Seric /* 2074454Seric ** MACVALUE -- return uninterpreted value of a macro. 2084454Seric ** 2094454Seric ** Parameters: 2104454Seric ** n -- the name of the macro. 2114454Seric ** 2124454Seric ** Returns: 2134454Seric ** The value of n. 2144454Seric ** 2154454Seric ** Side Effects: 2164454Seric ** none. 2174454Seric */ 2184454Seric 2194454Seric char * 220*8182Seric macvalue(n, e) 2214454Seric char n; 222*8182Seric register ENVELOPE *e; 2234454Seric { 224*8182Seric n &= 0177; 225*8182Seric while (e != NULL) 226*8182Seric { 227*8182Seric register char *p = e->e_macro[n]; 228*8182Seric 229*8182Seric if (p != NULL) 230*8182Seric return (p); 231*8182Seric e = e->e_parent; 232*8182Seric } 233*8182Seric return (NULL); 2344454Seric } 235