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