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