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