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