1 # include "useful.h" 2 3 SCCSID(@(#)macro.c 3.10 02/20/82); 4 5 char *Macro[128]; 6 extern int Debug; 7 8 /* 9 ** EXPAND -- macro expand a string using $x escapes. 10 ** 11 ** Parameters: 12 ** s -- the string to expand. 13 ** buf -- the place to put the expansion. 14 ** buflim -- the buffer limit, i.e., the address 15 ** of the last usable position in buf. 16 ** 17 ** Returns: 18 ** End of interpolated output. 19 ** 20 ** Side Effects: 21 ** none. 22 */ 23 24 char * 25 expand(s, buf, buflim) 26 register char *s; 27 register char *buf; 28 char *buflim; 29 { 30 register char *bp; 31 bool skipping; /* set if conditionally skipping output */ 32 33 # ifdef DEBUG 34 if (Debug > 3) 35 printf("expand(%s)\n", s); 36 # endif DEBUG 37 38 skipping = FALSE; 39 for (bp = buf; *s != '\0'; s++) 40 { 41 register char *q; 42 43 /* 44 ** Check for non-ordinary (special?) character -- 45 ** always escaped with dollar sign. 46 ** 'q' will be the interpolated quantity. 47 */ 48 49 q = NULL; 50 if (*s == '$') 51 { 52 char c; 53 54 c = *++s; 55 switch (c) 56 { 57 case '?': /* see if var set */ 58 c = *++s; 59 skipping = Macro[c] == NULL; 60 break; 61 62 case '|': /* else */ 63 skipping = !skipping; 64 break; 65 66 case '.': /* end if */ 67 skipping = FALSE; 68 break; 69 70 default: 71 q = Macro[c & 0177]; 72 break; 73 } 74 if (q == NULL && c != '$') 75 continue; 76 } 77 78 /* 79 ** Interpolate q or output one character 80 */ 81 82 if (skipping) 83 continue; 84 if (q != NULL) 85 bp = expand(q, bp, buflim); 86 else if (bp < buflim - 1) 87 *bp++ = *s; 88 } 89 *bp = '\0'; 90 91 # ifdef DEBUG 92 if (Debug > 3) 93 printf("expand ==> '%s'\n", buf); 94 # endif DEBUG 95 96 return (bp); 97 } 98 /* 99 ** DEFINE -- define a macro. 100 ** 101 ** this would be better done using a #define macro. 102 ** 103 ** Parameters: 104 ** n -- the macro name. 105 ** v -- the macro value. 106 ** 107 ** Returns: 108 ** none. 109 ** 110 ** Side Effects: 111 ** Macro[n] is defined. 112 ** 113 ** Notes: 114 ** There is one macro for each ASCII character, 115 ** although they are not all used. The currently 116 ** defined macros are: 117 ** 118 ** $a date in ARPANET format (preferring the Date: line 119 ** of the message) 120 ** $b the current date (as opposed to the date as found 121 ** the message) in ARPANET format 122 ** $c hop count 123 ** $d (current) date in UNIX (ctime) format 124 ** $f raw from address 125 ** $g translated from address 126 ** $h to host 127 ** $i official SMTP hostname, used in messages+ 128 ** $l UNIX-style from line+ 129 ** $n name of sendmail ("MAILER-DAEMON" on local 130 ** net typically)+ 131 ** $o delimiters ("operators") for address tokens+ 132 ** $p my process id in decimal 133 ** $q the string that becomes an address -- this is 134 ** normally used to combine $g & $x. 135 ** $r protocol used to talk to sender 136 ** $s sender's host name 137 ** $t the current time in seconds since 1/1/1970 138 ** $u to user 139 ** $v version number of sendmail 140 ** $x signature (full name) of from person 141 ** $y the tty id of our terminal 142 ** $z home directory of to person 143 ** 144 ** Macros marked with + must be defined in the 145 ** configuration file and are used internally, but 146 ** are not set. 147 ** 148 ** There are also some macros that can be used 149 ** arbitrarily to make the configuration file 150 ** cleaner. In general all upper-case letters 151 ** are available. 152 */ 153 154 define(n, v) 155 char n; 156 char *v; 157 { 158 # ifdef DEBUG 159 if (Debug > 3) 160 printf("define(%c as %s)\n", n, v); 161 # endif DEBUG 162 Macro[n & 0177] = v; 163 } 164 /* 165 ** MACVALUE -- return uninterpreted value of a macro. 166 ** 167 ** Parameters: 168 ** n -- the name of the macro. 169 ** 170 ** Returns: 171 ** The value of n. 172 ** 173 ** Side Effects: 174 ** none. 175 */ 176 177 char * 178 macvalue(n) 179 char n; 180 { 181 return (Macro[n & 0177]); 182 } 183