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