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