1 # include <stdio.h>
2 # include "sendmail.h"
3 # include <ctype.h>
4 
5 static char SccsId[] = "@(#)readcf.c	3.5	08/08/81";
6 
7 /*
8 **  READCF -- read control file.
9 **
10 **	This routine reads the control file and builds the internal
11 **	form.
12 **
13 **	Parameters:
14 **		cfname -- control file name.
15 **
16 **	Returns:
17 **		none.
18 **
19 **	Side Effects:
20 **		Builds several internal tables.
21 */
22 
23 struct rewrite	*RewriteRules[10];
24 
25 
26 readcf(cfname)
27 	char *cfname;
28 {
29 	FILE *cf;
30 	char buf[MAXLINE];
31 	register char *p;
32 	struct rewrite *rwp = NULL;
33 	extern char *xalloc();
34 	extern char **prescan();
35 	extern char **copyplist();
36 	extern char *rindex();
37 	extern char *newstr();
38 	int class;
39 	int ruleset = 0;
40 
41 	cf = fopen(cfname, "r");
42 	if (cf == NULL)
43 	{
44 		syserr("cannot open %s", cfname);
45 		exit(EX_OSFILE);
46 	}
47 
48 	while (fgets(buf, sizeof buf, cf) != NULL)
49 	{
50 		p = rindex(buf, '\n');
51 		if (p != NULL)
52 			*p = '\0';
53 
54 		switch (buf[0])
55 		{
56 		  case '\n':
57 		  case '\0':
58 		  case ' ':
59 		  case '\t':
60 		  case '#':		/* comment */
61 			break;
62 
63 		  case 'R':		/* rewriting rule */
64 			for (p = &buf[1]; *p != '\0' && *p != '\t'; p++)
65 				continue;
66 
67 			if (*p == '\0')
68 				syserr("invalid rewrite line \"%s\"", buf);
69 			else
70 			{
71 				if (rwp == NULL)
72 				{
73 					RewriteRules[ruleset] = rwp =
74 						(struct rewrite *) xalloc(sizeof *rwp);
75 				}
76 				else
77 				{
78 					rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
79 					rwp = rwp->r_next;
80 				}
81 				rwp->r_next = NULL;
82 
83 				rwp->r_lhs = prescan(&buf[1], '\t');
84 				if (rwp->r_lhs != NULL)
85 					rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
86 				while (*p == '\t')
87 					p++;
88 				rwp->r_rhs = prescan(p, '\t');
89 				if (rwp->r_rhs != NULL)
90 					rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
91 			}
92 			break;
93 
94 		  case 'S':		/* select rewriting set */
95 			ruleset = atoi(&buf[1]);
96 			rwp = NULL;
97 			break;
98 
99 		  case 'D':		/* macro definition */
100 			define(buf[1], newstr(&buf[2]));
101 			break;
102 
103 		  case 'H':		/* required header line */
104 			chompheader(&buf[1], TRUE);
105 			break;
106 
107 		  case 'C':		/* word class */
108 			class = buf[1];
109 			if (!isalpha(class))
110 				goto badline;
111 			if (isupper(class))
112 				class -= 'A';
113 			else
114 				class -= 'a';
115 
116 			/* scan the list of words and set class 'i' for all */
117 			for (p = &buf[2]; *p != '\0'; )
118 			{
119 				register char *wd;
120 				char delim;
121 				register STAB *s;
122 
123 				while (*p != '\0' && isspace(*p))
124 					p++;
125 				wd = p;
126 				while (*p != '\0' && !isspace(*p))
127 					p++;
128 				delim = *p;
129 				*p = '\0';
130 				if (wd[0] != '\0')
131 				{
132 					s = stab(wd, ST_ENTER);
133 					s->s_class |= 1 << class;
134 				}
135 				*p = delim;
136 			}
137 			break;
138 
139 		  default:
140 		  badline:
141 			syserr("unknown control line \"%s\"", buf);
142 		}
143 	}
144 
145 /*
146 	printrules();
147 */
148 }
149 /*
150 **  RWCRACK -- crack rewrite line.
151 **
152 **	Parameters:
153 **		l -- line to crack.
154 **
155 **	Returns:
156 **		local copy of cracked line.
157 **
158 **	Side Effects:
159 **		none.
160 */
161 
162 char **
163 rwcrack(l)
164 	register char *l;
165 {
166 	char *av[MAXATOM];
167 	int ac = 0;
168 	register char **avp;
169 	char buf[MAXNAME];
170 	register char *b;
171 	bool wasdelim = FALSE;
172 	char *delims = ":@!^.";
173 	extern char *index();
174 	bool tchange;
175 	extern char *newstr(), *xalloc();
176 
177 	for (avp = av; *l != '\0' && *l != '\n'; avp++)
178 	{
179 		b = buf;
180 		tchange = FALSE;
181 		while (!tchange)
182 		{
183 			if (*l != '$')
184 			{
185 				if (wasdelim || index(delims, *l) != NULL)
186 					tchange = TRUE;
187 				wasdelim = (index(delims, *l) != NULL);
188 				if (wasdelim)
189 					tchange = TRUE;
190 				*b++ = *l++;
191 				continue;
192 			}
193 
194 			tchange = TRUE;
195 			switch (*++l)
196 			{
197 			  case '$':		/* literal $ */
198 				*b++ = *l;
199 				break;
200 
201 			  case '+':		/* match anything */
202 				*b++ = MATCHANY;
203 				*b++ = *++l;
204 				break;
205 
206 			  case '-':		/* match one token */
207 				*b++ = MATCHONE;
208 				*b++ = *++l;
209 				break;
210 
211 			  case '#':		/* canonical net name */
212 				*b++ = CANONNET;
213 				break;
214 
215 			  case '@':		/* canonical host name */
216 				*b++ = CANONHOST;
217 				break;
218 
219 			  case ':':		/* canonical user name */
220 				*b++ = CANONUSER;
221 				break;
222 
223 			  default:
224 				*b++ = '$';
225 				l--;
226 				break;
227 			}
228 			l++;
229 		}
230 
231 		/* save the argument we have collected */
232 		*b = '\0';
233 		*avp = newstr(buf);
234 		ac++;
235 	}
236 
237 	/* allocate new space for vector */
238 	ac++;
239 	*avp = NULL;
240 	avp = (char **) xalloc(ac * sizeof *av);
241 	bmove(av, avp, ac * sizeof *av);
242 
243 	return (avp);
244 }
245 /*
246 **  PRINTRULES -- print rewrite rules (for debugging)
247 **
248 **	Parameters:
249 **		none.
250 **
251 **	Returns:
252 **		none.
253 **
254 **	Side Effects:
255 **		prints rewrite rules.
256 */
257 
258 printrules()
259 {
260 	register struct rewrite *rwp;
261 	register int ruleset;
262 
263 	for (ruleset = 0; ruleset < 10; ruleset++)
264 	{
265 		if (RewriteRules[ruleset] == NULL)
266 			continue;
267 		printf("\n----Rule Set %d:\n", ruleset);
268 
269 		for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next)
270 		{
271 			register char **av;
272 
273 			printf("\n");
274 			for (av = rwp->r_lhs; *av != NULL; av++)
275 			{
276 				xputs(*av);
277 				putchar('_');
278 			}
279 			printf("\n\t");
280 			for (av = rwp->r_rhs; *av != NULL; av++)
281 			{
282 				xputs(*av);
283 				putchar('_');
284 			}
285 			printf("\n");
286 		}
287 	}
288 }
289