1 # include "useful.h" 2 3 static char SccsId[] = "@(#)macro.c 3.3 08/22/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 ** buf. 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 *q; 31 register char *bp; 32 bool skipping; 33 34 # ifdef DEBUG 35 if (Debug > 3) 36 printf("expand(%s)\n", s); 37 # endif DEBUG 38 39 skipping = FALSE; 40 for (bp = buf; *s != '\0'; s++) 41 { 42 /* q will be the interpolated quantity */ 43 q = NULL; 44 if (*s == '$') 45 { 46 char c; 47 48 c = *++s; 49 switch (c) 50 { 51 case '?': /* see if var set */ 52 c = *++s; 53 skipping = Macro[c] == NULL; 54 break; 55 56 case ':': /* else */ 57 skipping = !skipping; 58 break; 59 60 case '.': /* end if */ 61 skipping = FALSE; 62 break; 63 64 default: 65 q = Macro[c & 0177]; 66 break; 67 } 68 if (q == NULL && c != '$') 69 continue; 70 } 71 72 /* 73 ** Interpolate q or output one character 74 */ 75 76 if (skipping) 77 continue; 78 if (q != NULL) 79 bp = expand(q, bp, buflim); 80 else if (bp < buflim - 1) 81 *bp++ = *s; 82 } 83 *bp = '\0'; 84 85 # ifdef DEBUG 86 if (Debug > 3) 87 printf("expand ==> '%s'\n", buf); 88 # endif DEBUG 89 90 return (bp); 91 } 92 /* 93 ** DEFINE -- define a macro. 94 ** 95 ** this would be better done using a #define macro. 96 ** 97 ** Parameters: 98 ** n -- the macro name. 99 ** v -- the macro value. 100 ** 101 ** Returns: 102 ** none. 103 ** 104 ** Side Effects: 105 ** Macro[n] is defined. 106 ** 107 ** Notes: 108 ** There is one macro for each ASCII character, 109 ** although they are not all used. The currently 110 ** defined macros are: 111 ** 112 ** $a date in ARPANET format (preferring the Date: line 113 ** of the message) 114 ** $b the current date (as opposed to the date as found 115 ** the message) in ARPANET format 116 ** $c hop count 117 ** $d (current) date in UNIX (ctime) format 118 ** $f raw from address 119 ** $g translated from address 120 ** $h to host 121 ** $l UNIX-style from line+ 122 ** $n name of sendmail ("MAILER-DAEMON" on local 123 ** net typically)+ 124 ** $o delimiters ("operators") for address tokens+ 125 ** $p my process id in decimal 126 ** $t the current time in seconds since 1/1/1970 127 ** $u to user 128 ** $v version number of sendmail 129 ** $x signature (full name) of from person 130 ** $y the tty id of our terminal 131 ** $z home directory of to person 132 ** 133 ** Macros marked with + must be defined in the 134 ** configuration file and are used internally, but 135 ** are not set. 136 ** 137 ** There are also some macros that can be used 138 ** arbitrarily to make the configuration file 139 ** cleaner. In general all upper-case letters 140 ** are available. 141 */ 142 143 define(n, v) 144 char n; 145 char *v; 146 { 147 # ifdef DEBUG 148 if (Debug > 3) 149 printf("define(%c as %s)\n", n, v); 150 # endif DEBUG 151 Macro[n & 0177] = v; 152 } 153