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