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.2 (Berkeley) 06/07/85"; 13 #endif not lint 14 15 # include "sendmail.h" 16 17 /* 18 ** EXPAND -- macro expand a string using $x escapes. 19 ** 20 ** Parameters: 21 ** s -- the string to expand. 22 ** buf -- the place to put the expansion. 23 ** buflim -- the buffer limit, i.e., the address 24 ** of the last usable position in buf. 25 ** e -- envelope in which to work. 26 ** 27 ** Returns: 28 ** none. 29 ** 30 ** Side Effects: 31 ** none. 32 */ 33 34 expand(s, buf, buflim, e) 35 register char *s; 36 register char *buf; 37 char *buflim; 38 register ENVELOPE *e; 39 { 40 register char *xp; 41 register char *q; 42 bool skipping; /* set if conditionally skipping output */ 43 bool recurse = FALSE; /* set if recursion required */ 44 int i; 45 char xbuf[BUFSIZ]; 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 (xp = xbuf; *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 '\001': /* macro interpolation */ 87 c = *++s; 88 q = macvalue(c & 0177, e); 89 if (q == NULL) 90 continue; 91 break; 92 } 93 94 /* 95 ** Interpolate q or output one character 96 */ 97 98 if (skipping || xp >= &xbuf[sizeof xbuf]) 99 continue; 100 if (q == NULL) 101 *xp++ = c; 102 else 103 { 104 /* copy to end of q or max space remaining in buf */ 105 while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1]) 106 { 107 if (iscntrl(c) && !isspace(c)) 108 recurse = TRUE; 109 *xp++ = c; 110 } 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 (recurse) 126 { 127 expand(xbuf, buf, buflim, e); 128 return; 129 } 130 131 /* copy results out */ 132 i = buflim - buf - 1; 133 if (i > xp - xbuf) 134 i = xp - xbuf; 135 bcopy(xbuf, buf, i); 136 buf[i] = '\0'; 137 } 138 /* 139 ** DEFINE -- define a macro. 140 ** 141 ** this would be better done using a #define macro. 142 ** 143 ** Parameters: 144 ** n -- the macro name. 145 ** v -- the macro value. 146 ** e -- the envelope to store the definition in. 147 ** 148 ** Returns: 149 ** none. 150 ** 151 ** Side Effects: 152 ** e->e_macro[n] is defined. 153 ** 154 ** Notes: 155 ** There is one macro for each ASCII character, 156 ** although they are not all used. The currently 157 ** defined macros are: 158 ** 159 ** $a date in ARPANET format (preferring the Date: line 160 ** of the message) 161 ** $b the current date (as opposed to the date as found 162 ** the message) in ARPANET format 163 ** $c hop count 164 ** $d (current) date in UNIX (ctime) format 165 ** $e the SMTP entry message+ 166 ** $f raw from address 167 ** $g translated from address 168 ** $h to host 169 ** $i queue id 170 ** $j official SMTP hostname, used in messages+ 171 ** $l UNIX-style from line+ 172 ** $n name of sendmail ("MAILER-DAEMON" on local 173 ** net typically)+ 174 ** $o delimiters ("operators") for address tokens+ 175 ** $p my process id in decimal 176 ** $q the string that becomes an address -- this is 177 ** normally used to combine $g & $x. 178 ** $r protocol used to talk to sender 179 ** $s sender's host name 180 ** $t the current time in seconds since 1/1/1970 181 ** $u to user 182 ** $v version number of sendmail 183 ** $w our host name (if it can be determined) 184 ** $x signature (full name) of from person 185 ** $y the tty id of our terminal 186 ** $z home directory of to person 187 ** 188 ** Macros marked with + must be defined in the 189 ** configuration file and are used internally, but 190 ** are not set. 191 ** 192 ** There are also some macros that can be used 193 ** arbitrarily to make the configuration file 194 ** cleaner. In general all upper-case letters 195 ** are available. 196 */ 197 198 define(n, v, e) 199 char n; 200 char *v; 201 register ENVELOPE *e; 202 { 203 # ifdef DEBUG 204 if (tTd(35, 3)) 205 { 206 printf("define(%c as ", n); 207 xputs(v); 208 printf(")\n"); 209 } 210 # endif DEBUG 211 e->e_macro[n & 0177] = v; 212 } 213 /* 214 ** MACVALUE -- return uninterpreted value of a macro. 215 ** 216 ** Parameters: 217 ** n -- the name of the macro. 218 ** 219 ** Returns: 220 ** The value of n. 221 ** 222 ** Side Effects: 223 ** none. 224 */ 225 226 char * 227 macvalue(n, e) 228 char n; 229 register ENVELOPE *e; 230 { 231 n &= 0177; 232 while (e != NULL) 233 { 234 register char *p = e->e_macro[n]; 235 236 if (p != NULL) 237 return (p); 238 e = e->e_parent; 239 } 240 return (NULL); 241 } 242