1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)macro.c 6.2 (Berkeley) 01/18/93"; 11 #endif /* not lint */ 12 13 # include "sendmail.h" 14 15 /* 16 ** EXPAND -- macro expand a string using $x escapes. 17 ** 18 ** Parameters: 19 ** s -- the string to expand. 20 ** buf -- the place to put the expansion. 21 ** buflim -- the buffer limit, i.e., the address 22 ** of the last usable position in buf. 23 ** e -- envelope in which to work. 24 ** 25 ** Returns: 26 ** none. 27 ** 28 ** Side Effects: 29 ** none. 30 */ 31 32 expand(s, buf, buflim, e) 33 register char *s; 34 register char *buf; 35 char *buflim; 36 register ENVELOPE *e; 37 { 38 register char *xp; 39 register char *q; 40 bool skipping; /* set if conditionally skipping output */ 41 bool recurse = FALSE; /* set if recursion required */ 42 int i; 43 int iflev; /* if nesting level */ 44 char xbuf[BUFSIZ]; 45 extern char *macvalue(); 46 47 if (tTd(35, 24)) 48 { 49 printf("expand("); 50 xputs(s); 51 printf(")\n"); 52 } 53 54 skipping = FALSE; 55 iflev = 0; 56 if (s == NULL) 57 s = ""; 58 for (xp = xbuf; *s != '\0'; s++) 59 { 60 char c; 61 62 /* 63 ** Check for non-ordinary (special?) character. 64 ** 'q' will be the interpolated quantity. 65 */ 66 67 q = NULL; 68 c = *s; 69 switch (c) 70 { 71 case CONDIF: /* see if var set */ 72 if (iflev++ <= 0) 73 { 74 c = *++s; 75 skipping = macvalue(c, e) == NULL; 76 continue; 77 } 78 break; 79 80 case CONDELSE: /* change state of skipping */ 81 if (iflev == 1) 82 skipping = !skipping; 83 continue; 84 85 case CONDFI: /* stop skipping */ 86 if (--iflev <= 0) 87 { 88 skipping = FALSE; 89 continue; 90 } 91 break; 92 93 case '\001': /* macro interpolation */ 94 c = *++s; 95 q = macvalue(c & 0177, e); 96 if (q == NULL) 97 continue; 98 break; 99 } 100 101 /* 102 ** Interpolate q or output one character 103 */ 104 105 if (skipping || xp >= &xbuf[sizeof xbuf]) 106 continue; 107 if (q == NULL) 108 *xp++ = c; 109 else 110 { 111 /* copy to end of q or max space remaining in buf */ 112 while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 113 { 114 if (iscntrl(c) && !isspace(c)) 115 recurse = TRUE; 116 *xp++ = c; 117 } 118 } 119 } 120 *xp = '\0'; 121 122 if (tTd(35, 24)) 123 { 124 printf("expand ==> "); 125 xputs(xbuf); 126 printf("\n"); 127 } 128 129 /* recurse as appropriate */ 130 if (recurse) 131 { 132 expand(xbuf, buf, buflim, e); 133 return; 134 } 135 136 /* copy results out */ 137 i = buflim - buf - 1; 138 if (i > xp - xbuf) 139 i = xp - xbuf; 140 bcopy(xbuf, buf, i); 141 buf[i] = '\0'; 142 } 143 /* 144 ** DEFINE -- define a macro. 145 ** 146 ** this would be better done using a #define macro. 147 ** 148 ** Parameters: 149 ** n -- the macro name. 150 ** v -- the macro value. 151 ** e -- the envelope to store the definition in. 152 ** 153 ** Returns: 154 ** none. 155 ** 156 ** Side Effects: 157 ** e->e_macro[n] is defined. 158 ** 159 ** Notes: 160 ** There is one macro for each ASCII character, 161 ** although they are not all used. The currently 162 ** defined macros are: 163 ** 164 ** $a date in ARPANET format (preferring the Date: line 165 ** of the message) 166 ** $b the current date (as opposed to the date as found 167 ** the message) in ARPANET format 168 ** $c hop count 169 ** $d (current) date in UNIX (ctime) format 170 ** $e the SMTP entry message+ 171 ** $f raw from address 172 ** $g translated from address 173 ** $h to host 174 ** $i queue id 175 ** $j official SMTP hostname, used in messages+ 176 ** $l UNIX-style from line+ 177 ** $n name of sendmail ("MAILER-DAEMON" on local 178 ** net typically)+ 179 ** $o delimiters ("operators") for address tokens+ 180 ** $p my process id in decimal 181 ** $q the string that becomes an address -- this is 182 ** normally used to combine $g & $x. 183 ** $r protocol used to talk to sender 184 ** $s sender's host name 185 ** $t the current time in seconds since 1/1/1970 186 ** $u to user 187 ** $v version number of sendmail 188 ** $w our host name (if it can be determined) 189 ** $x signature (full name) of from person 190 ** $y the tty id of our terminal 191 ** $z home directory of to person 192 ** 193 ** Macros marked with + must be defined in the 194 ** configuration file and are used internally, but 195 ** are not set. 196 ** 197 ** There are also some macros that can be used 198 ** arbitrarily to make the configuration file 199 ** cleaner. In general all upper-case letters 200 ** are available. 201 */ 202 203 define(n, v, e) 204 char n; 205 char *v; 206 register ENVELOPE *e; 207 { 208 if (tTd(35, 9)) 209 { 210 printf("define(%c as ", n); 211 xputs(v); 212 printf(")\n"); 213 } 214 e->e_macro[n & 0177] = v; 215 } 216 /* 217 ** MACVALUE -- return uninterpreted value of a macro. 218 ** 219 ** Parameters: 220 ** n -- the name of the macro. 221 ** 222 ** Returns: 223 ** The value of n. 224 ** 225 ** Side Effects: 226 ** none. 227 */ 228 229 char * 230 macvalue(n, e) 231 char n; 232 register ENVELOPE *e; 233 { 234 n &= 0177; 235 while (e != NULL) 236 { 237 register char *p = e->e_macro[n]; 238 239 if (p != NULL) 240 return (p); 241 e = e->e_parent; 242 } 243 return (NULL); 244 } 245