1 # include "useful.h" 2 3 static char SccsId[] = "@(#)macro.c 3.4 09/06/81"; 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 ** $l UNIX-style from line+ 128 ** $n name of sendmail ("MAILER-DAEMON" on local 129 ** net typically)+ 130 ** $o delimiters ("operators") for address tokens+ 131 ** $p my process id in decimal 132 ** $t the current time in seconds since 1/1/1970 133 ** $u to user 134 ** $v version number of sendmail 135 ** $x signature (full name) of from person 136 ** $y the tty id of our terminal 137 ** $z home directory of to person 138 ** 139 ** Macros marked with + must be defined in the 140 ** configuration file and are used internally, but 141 ** are not set. 142 ** 143 ** There are also some macros that can be used 144 ** arbitrarily to make the configuration file 145 ** cleaner. In general all upper-case letters 146 ** are available. 147 */ 148 149 define(n, v) 150 char n; 151 char *v; 152 { 153 # ifdef DEBUG 154 if (Debug > 3) 155 printf("define(%c as %s)\n", n, v); 156 # endif DEBUG 157 Macro[n & 0177] = v; 158 } 159