1 # include "sendmail.h"
2 
3 static char SccsId[] = "@(#)readcf.c	3.10	08/20/81";
4 
5 /*
6 **  READCF -- read control file.
7 **
8 **	This routine reads the control file and builds the internal
9 **	form.
10 **
11 **	Parameters:
12 **		cfname -- control file name.
13 **
14 **	Returns:
15 **		none.
16 **
17 **	Side Effects:
18 **		Builds several internal tables.
19 */
20 
21 struct rewrite	*RewriteRules[10];
22 
23 
24 readcf(cfname)
25 	char *cfname;
26 {
27 	FILE *cf;
28 	char buf[MAXLINE];
29 	register char *p;
30 	struct rewrite *rwp = NULL;
31 	extern char **prescan();
32 	extern char **copyplist();
33 	int class;
34 	int ruleset = 0;
35 
36 	cf = fopen(cfname, "r");
37 	if (cf == NULL)
38 	{
39 		syserr("cannot open %s", cfname);
40 		exit(EX_OSFILE);
41 	}
42 
43 	while (fgets(buf, sizeof buf, cf) != NULL)
44 	{
45 		p = rindex(buf, '\n');
46 		if (p != NULL)
47 			*p = '\0';
48 
49 		switch (buf[0])
50 		{
51 		  case '\n':
52 		  case '\0':
53 		  case ' ':
54 		  case '\t':
55 		  case '#':		/* comment */
56 			break;
57 
58 		  case 'R':		/* rewriting rule */
59 			for (p = &buf[1]; *p != '\0' && *p != '\t'; p++)
60 				continue;
61 
62 			if (*p == '\0')
63 				syserr("invalid rewrite line \"%s\"", buf);
64 			else
65 			{
66 				if (rwp == NULL)
67 				{
68 					RewriteRules[ruleset] = rwp =
69 						(struct rewrite *) xalloc(sizeof *rwp);
70 				}
71 				else
72 				{
73 					rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
74 					rwp = rwp->r_next;
75 				}
76 				rwp->r_next = NULL;
77 
78 				rwp->r_lhs = prescan(&buf[1], '\t');
79 				if (rwp->r_lhs != NULL)
80 					rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
81 				while (*p == '\t')
82 					p++;
83 				rwp->r_rhs = prescan(p, '\t');
84 				if (rwp->r_rhs != NULL)
85 					rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
86 			}
87 			break;
88 
89 		  case 'S':		/* select rewriting set */
90 			ruleset = atoi(&buf[1]);
91 			rwp = NULL;
92 			break;
93 
94 		  case 'D':		/* macro definition */
95 			define(buf[1], newstr(&buf[2]));
96 			break;
97 
98 		  case 'H':		/* required header line */
99 			(void) chompheader(&buf[1], TRUE);
100 			break;
101 
102 		  case 'C':		/* word class */
103 			class = buf[1];
104 			if (!isalpha(class))
105 				goto badline;
106 			if (isupper(class))
107 				class -= 'A';
108 			else
109 				class -= 'a';
110 
111 			/* scan the list of words and set class 'i' for all */
112 			for (p = &buf[2]; *p != '\0'; )
113 			{
114 				register char *wd;
115 				char delim;
116 				register STAB *s;
117 
118 				while (*p != '\0' && isspace(*p))
119 					p++;
120 				wd = p;
121 				while (*p != '\0' && !isspace(*p))
122 					p++;
123 				delim = *p;
124 				*p = '\0';
125 				if (wd[0] != '\0')
126 				{
127 					s = stab(wd, ST_CLASS, ST_ENTER);
128 					s->s_class |= 1 << class;
129 				}
130 				*p = delim;
131 			}
132 			break;
133 
134 		  case 'M':		/* define mailer */
135 			makemailer(&buf[1]);
136 			break;
137 
138 		  default:
139 		  badline:
140 			syserr("unknown control line \"%s\"", buf);
141 		}
142 	}
143 }
144 /*
145 **  MAKEMAILER -- define a new mailer.
146 **
147 **	Parameters:
148 **		line -- description of mailer.  This is in tokens
149 **			separated by white space.  The fields are:
150 **			* the name of the mailer, as refered to
151 **			  in the rewriting rules.
152 **			* the pathname of the program to fork to
153 **			  execute it.
154 **			* the options needed by this program.
155 **			* the macro string needed to translate
156 **			  a local "from" name to one that can be
157 **			  returned to this machine.
158 **			* the argument vector (a series of parameters).
159 **
160 **	Returns:
161 **		none.
162 **
163 **	Side Effects:
164 **		enters the mailer into the mailer table.
165 */
166 
167 # define SETWORD \
168 		{ \
169 			while (*p != '\0' && isspace(*p)) \
170 				p++; \
171 			q = p; \
172 			while (*p != '\0' && !isspace(*p)) \
173 				p++; \
174 			if (*p != '\0') \
175 				*p++ = '\0'; \
176 		}
177 
178 makemailer(line)
179 	char *line;
180 {
181 	register char *p;
182 	register char *q;
183 	char *mname;
184 	char *mpath;
185 	int mopts;
186 	char *mfrom;
187 	register struct mailer *m;
188 	char *margv[MAXPV + 1];
189 	register int i;
190 	extern int NextMailer;
191 
192 	if (NextMailer >= MAXMAILERS)
193 	{
194 		syserr("Too many mailers defined");
195 		return;
196 	}
197 
198 	/* collect initial information */
199 	p = line;
200 	SETWORD;
201 	mname = q;
202 	SETWORD;
203 	mpath = q;
204 	SETWORD;
205 	mopts = crackopts(q);
206 	SETWORD;
207 	mfrom = q;
208 
209 	if (*p == '\0')
210 	{
211 		syserr("invalid M line in configuration file");
212 		return;
213 	}
214 
215 	/* allocate a mailer */
216 	m = (struct mailer *) xalloc(sizeof *m);
217 	m->m_name = newstr(mname);
218 	m->m_mailer = newstr(mpath);
219 	m->m_flags = mopts;
220 	m->m_from = newstr(mfrom);
221 	m->m_badstat = EX_UNAVAILABLE;
222 	m->m_sendq = NULL;
223 	Mailer[NextMailer++] = m;
224 
225 	/* collect the argument vector */
226 	for (i = 0; i < MAXPV - 1 && *p != '\0'; i++)
227 	{
228 		SETWORD;
229 		margv[i] = newstr(q);
230 	}
231 	margv[i++] = NULL;
232 
233 	/* save the argv */
234 	m->m_argv = (char **) xalloc(sizeof margv[0] * i);
235 	bmove((char *) margv, (char *) m->m_argv, sizeof margv[0] * i);
236 }
237 /*
238 **  PRINTRULES -- print rewrite rules (for debugging)
239 **
240 **	Parameters:
241 **		none.
242 **
243 **	Returns:
244 **		none.
245 **
246 **	Side Effects:
247 **		prints rewrite rules.
248 */
249 
250 printrules()
251 {
252 	register struct rewrite *rwp;
253 	register int ruleset;
254 
255 	for (ruleset = 0; ruleset < 10; ruleset++)
256 	{
257 		if (RewriteRules[ruleset] == NULL)
258 			continue;
259 		printf("\n----Rule Set %d:\n", ruleset);
260 
261 		for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next)
262 		{
263 			register char **av;
264 
265 			printf("\n");
266 			for (av = rwp->r_lhs; *av != NULL; av++)
267 			{
268 				xputs(*av);
269 				putchar('_');
270 			}
271 			printf("\n\t");
272 			for (av = rwp->r_rhs; *av != NULL; av++)
273 			{
274 				xputs(*av);
275 				putchar('_');
276 			}
277 			printf("\n");
278 		}
279 	}
280 }
281 /*
282 **  CRACKOPTS -- crack mailer options
283 **
284 **	These options modify the functioning of the mailer
285 **	from the configuration table.
286 **
287 **	Parameters:
288 **		p -- pointer to vector of options.
289 **
290 **	Returns:
291 **		option list in binary.
292 **
293 **	Side Effects:
294 **		none.
295 */
296 
297 struct optlist
298 {
299 	char	opt_name;	/* external name of option */
300 	int	opt_value;	/* internal name of option */
301 };
302 struct optlist	OptList[] =
303 {
304 	'f',	M_FOPT,
305 	'r',	M_ROPT,
306 	'q',	M_QUIET,
307 	'S',	M_RESTR,
308 	'n',	M_NHDR,
309 	'l',	M_NOHOST,
310 	's',	M_STRIPQ,
311 	'm',	M_MUSER,
312 	'F',	M_NEEDFROM,
313 	'D',	M_NEEDDATE,
314 	'M',	M_MSGID,
315 	'u',	M_USR_UPPER,
316 	'h',	M_HST_UPPER,
317 	'x',	M_FULLNAME,
318 	'A',	M_ARPAFMT,
319 	'L',	M_FINAL,
320 	0,	0
321 };
322 
323 crackopts(p)
324 	register char *p;
325 {
326 	register struct optlist *o;
327 	register int opts = 0;
328 
329 	while (*p != '\0')
330 	{
331 		for (o = OptList; o->opt_name != '\0' && o->opt_name != *p; o++)
332 			continue;
333 		if (o->opt_name == '\0')
334 			syserr("bad mailer option %c", *p);
335 		opts |= o->opt_value;
336 		p++;
337 	}
338 	return (opts);
339 }
340