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