xref: /original-bsd/sbin/mount_portal/conf.c (revision e58c8952)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * All rights reserved.
5  *
6  * This code is derived from software donated to Berkeley by
7  * Jan-Simon Pendry.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)conf.c	8.2 (Berkeley) 03/27/94
12  *
13  * $Id: conf.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <regexp.h>
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/syslog.h>
26 
27 #include "portald.h"
28 
29 #define	ALLOC(ty)	(xmalloc(sizeof(ty)))
30 
31 typedef struct path path;
32 struct path {
33 	qelem p_q;		/* 2-way linked list */
34 	int p_lno;		/* Line number of this record */
35 	char *p_args;		/* copy of arg string (malloc) */
36 	char *p_key;		/* Pathname to match (also p_argv[0]) */
37 	regexp *p_re;		/* RE to match against pathname (malloc) */
38 	int p_argc;		/* number of elements in arg string */
39 	char **p_argv;		/* argv[] pointers into arg string (malloc) */
40 };
41 
42 static char *conf_file;		/* XXX for regerror */
43 static path *curp;		/* XXX for regerror */
44 
45 /*
46  * Add an element to a 2-way list,
47  * just after (pred)
48  */
49 static void ins_que(elem, pred)
50 qelem *elem, *pred;
51 {
52 	qelem *p = pred->q_forw;
53 	elem->q_back = pred;
54 	elem->q_forw = p;
55 	pred->q_forw = elem;
56 	p->q_back = elem;
57 }
58 
59 /*
60  * Remove an element from a 2-way list
61  */
62 static void rem_que(elem)
63 qelem *elem;
64 {
65 	qelem *p = elem->q_forw;
66 	qelem *p2 = elem->q_back;
67 	p2->q_forw = p;
68 	p->q_back = p2;
69 }
70 
71 /*
72  * Error checking malloc
73  */
74 static void *xmalloc(siz)
75 unsigned siz;
76 {
77 	void *p = malloc(siz);
78 	if (p)
79 		return (p);
80 	syslog(LOG_ALERT, "malloc: failed to get %d bytes", siz);
81 	exit(1);
82 }
83 
84 /*
85  * Insert the path in the list.
86  * If there is already an element with the same key then
87  * the *second* one is ignored (return 0).  If the key is
88  * not found then the path is added to the end of the list
89  * and 1 is returned.
90  */
91 static int pinsert(p0, q0)
92 path *p0;
93 qelem *q0;
94 {
95 	qelem *q;
96 
97 	if (p0->p_argc == 0)
98 		return (0);
99 
100 	for (q = q0->q_forw; q != q0; q = q->q_forw) {
101 		path *p = (path *) q;
102 		if (strcmp(p->p_key, p0->p_key) == 0)
103 			return (0);
104 	}
105 	ins_que(&p0->p_q, q0->q_back);
106 	return (1);
107 
108 }
109 
110 void regerror(s)
111 const char *s;
112 {
113 	syslog(LOG_ERR, "%s:%s: regcomp %s: %s",
114 			conf_file, curp->p_lno, curp->p_key, s);
115 }
116 
117 static path *palloc(cline, lno)
118 char *cline;
119 int lno;
120 {
121 	int c;
122 	char *s;
123 	char *key;
124 	path *p;
125 	char **ap;
126 
127 	/*
128 	 * Implement comment chars
129 	 */
130 	s = strchr(cline, '#');
131 	if (s)
132 		*s = 0;
133 
134 	/*
135 	 * Do a pass through the string to count the number
136 	 * of arguments
137 	 */
138 	c = 0;
139 	key = strdup(cline);
140 	for (s = key; s != NULL; ) {
141 		char *val;
142 		while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
143 			;
144 		if (val)
145 			c++;
146 	}
147 	c++;
148 	free(key);
149 
150 	if (c <= 1)
151 		return (0);
152 
153 	/*
154 	 * Now do another pass and generate a new path structure
155 	 */
156 	p = ALLOC(path);
157 	p->p_argc = 0;
158 	p->p_argv = xmalloc(c * sizeof(char *));
159 	p->p_args = strdup(cline);
160 	ap = p->p_argv;
161 	for (s = p->p_args; s != NULL; ) {
162 		char *val;
163 		while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
164 			;
165 		if (val) {
166 			*ap++ = val;
167 			p->p_argc++;
168 		}
169 	}
170 	*ap = 0;
171 
172 #ifdef DEBUG
173 	for (c = 0; c < p->p_argc; c++)
174 		printf("%sv[%d] = %s\n", c?"\t":"", c, p->p_argv[c]);
175 #endif
176 
177 	p->p_key = p->p_argv[0];
178 	if (strpbrk(p->p_key, RE_CHARS)) {
179 		curp = p;			/* XXX */
180 		p->p_re = regcomp(p->p_key);
181 		curp = 0;			/* XXX */
182 	} else {
183 		p->p_re = 0;
184 	}
185 	p->p_lno = lno;
186 
187 	return (p);
188 }
189 
190 /*
191  * Free a path structure
192  */
193 static void pfree(p)
194 path *p;
195 {
196 	free(p->p_args);
197 	if (p->p_re)
198 		free((char *) p->p_re);
199 	free((char *) p->p_argv);
200 	free((char *) p);
201 }
202 
203 /*
204  * Discard all currently held path structures on q0.
205  * and add all the ones on xq.
206  */
207 static void preplace(q0, xq)
208 qelem *q0;
209 qelem *xq;
210 {
211 	/*
212 	 * While the list is not empty,
213 	 * take the first element off the list
214 	 * and free it.
215 	 */
216 	while (q0->q_forw != q0) {
217 		qelem *q = q0->q_forw;
218 		rem_que(q);
219 		pfree((path *) q);
220 	}
221 	while (xq->q_forw != xq) {
222 		qelem *q = xq->q_forw;
223 		rem_que(q);
224 		ins_que(q, q0);
225 	}
226 }
227 
228 /*
229  * Read the lines from the configuration file and
230  * add them to the list of paths.
231  */
232 static void readfp(q0, fp)
233 qelem *q0;
234 FILE *fp;
235 {
236 	char cline[LINE_MAX];
237 	int nread = 0;
238 	qelem q;
239 
240 	/*
241 	 * Make a new empty list.
242 	 */
243 	q.q_forw = q.q_back = &q;
244 
245 	/*
246 	 * Read the lines from the configuration file.
247 	 */
248 	while (fgets(cline, sizeof(cline), fp)) {
249 		path *p = palloc(cline, nread+1);
250 		if (p && !pinsert(p, &q))
251 			pfree(p);
252 		nread++;
253 	}
254 
255 	/*
256 	 * If some records were read, then throw
257 	 * away the old list and replace with the
258 	 * new one.
259 	 */
260 	if (nread)
261 		preplace(q0, &q);
262 }
263 
264 /*
265  * Read the configuration file (conf) and replace
266  * the existing path list with the new version.
267  * If the file is not readable, then no changes take place
268  */
269 void conf_read(q, conf)
270 qelem *q;
271 char *conf;
272 {
273 	FILE *fp = fopen(conf, "r");
274 	if (fp) {
275 		conf_file = conf;		/* XXX */
276 		readfp(q, fp);
277 		conf_file = 0;		/* XXX */
278 		(void) fclose(fp);
279 	} else {
280 		syslog(LOG_ERR, "open config file \"%s\": %s", conf, strerror(errno));
281 	}
282 }
283 
284 
285 char **conf_match(q0, key)
286 qelem *q0;
287 char *key;
288 {
289 	qelem *q;
290 
291 	for (q = q0->q_forw; q != q0; q = q->q_forw) {
292 		path *p = (path *) q;
293 		if (p->p_re) {
294 			if (regexec(p->p_re, key))
295 				return (p->p_argv+1);
296 		} else {
297 			if (strncmp(p->p_key, key, strlen(p->p_key)) == 0)
298 				return (p->p_argv+1);
299 		}
300 	}
301 
302 	return (0);
303 }
304