xref: /netbsd-src/sbin/mount_portal/conf.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
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  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	from: Id: conf.c,v 1.2 1992/05/27 07:09:27 jsp Exp
38  *	from: @(#)conf.c	8.2 (Berkeley) 3/27/94
39  *	$Id: conf.c,v 1.2 1994/06/08 19:24:46 mycroft Exp $
40  */
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <limits.h>
48 #include <regexp.h>
49 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/syslog.h>
52 
53 #include "portald.h"
54 
55 #define	ALLOC(ty)	(xmalloc(sizeof(ty)))
56 
57 typedef struct path path;
58 struct path {
59 	qelem p_q;		/* 2-way linked list */
60 	int p_lno;		/* Line number of this record */
61 	char *p_args;		/* copy of arg string (malloc) */
62 	char *p_key;		/* Pathname to match (also p_argv[0]) */
63 	regexp *p_re;		/* RE to match against pathname (malloc) */
64 	int p_argc;		/* number of elements in arg string */
65 	char **p_argv;		/* argv[] pointers into arg string (malloc) */
66 };
67 
68 static char *conf_file;		/* XXX for regerror */
69 static path *curp;		/* XXX for regerror */
70 
71 /*
72  * Add an element to a 2-way list,
73  * just after (pred)
74  */
75 static void ins_que(elem, pred)
76 qelem *elem, *pred;
77 {
78 	qelem *p = pred->q_forw;
79 	elem->q_back = pred;
80 	elem->q_forw = p;
81 	pred->q_forw = elem;
82 	p->q_back = elem;
83 }
84 
85 /*
86  * Remove an element from a 2-way list
87  */
88 static void rem_que(elem)
89 qelem *elem;
90 {
91 	qelem *p = elem->q_forw;
92 	qelem *p2 = elem->q_back;
93 	p2->q_forw = p;
94 	p->q_back = p2;
95 }
96 
97 /*
98  * Error checking malloc
99  */
100 static void *xmalloc(siz)
101 unsigned siz;
102 {
103 	void *p = malloc(siz);
104 	if (p)
105 		return (p);
106 	syslog(LOG_ALERT, "malloc: failed to get %d bytes", siz);
107 	exit(1);
108 }
109 
110 /*
111  * Insert the path in the list.
112  * If there is already an element with the same key then
113  * the *second* one is ignored (return 0).  If the key is
114  * not found then the path is added to the end of the list
115  * and 1 is returned.
116  */
117 static int pinsert(p0, q0)
118 path *p0;
119 qelem *q0;
120 {
121 	qelem *q;
122 
123 	if (p0->p_argc == 0)
124 		return (0);
125 
126 	for (q = q0->q_forw; q != q0; q = q->q_forw) {
127 		path *p = (path *) q;
128 		if (strcmp(p->p_key, p0->p_key) == 0)
129 			return (0);
130 	}
131 	ins_que(&p0->p_q, q0->q_back);
132 	return (1);
133 
134 }
135 
136 void regerror(s)
137 const char *s;
138 {
139 	syslog(LOG_ERR, "%s:%s: regcomp %s: %s",
140 			conf_file, curp->p_lno, curp->p_key, s);
141 }
142 
143 static path *palloc(cline, lno)
144 char *cline;
145 int lno;
146 {
147 	int c;
148 	char *s;
149 	char *key;
150 	path *p;
151 	char **ap;
152 
153 	/*
154 	 * Implement comment chars
155 	 */
156 	s = strchr(cline, '#');
157 	if (s)
158 		*s = 0;
159 
160 	/*
161 	 * Do a pass through the string to count the number
162 	 * of arguments
163 	 */
164 	c = 0;
165 	key = strdup(cline);
166 	for (s = key; s != NULL; ) {
167 		char *val;
168 		while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
169 			;
170 		if (val)
171 			c++;
172 	}
173 	c++;
174 	free(key);
175 
176 	if (c <= 1)
177 		return (0);
178 
179 	/*
180 	 * Now do another pass and generate a new path structure
181 	 */
182 	p = ALLOC(path);
183 	p->p_argc = 0;
184 	p->p_argv = xmalloc(c * sizeof(char *));
185 	p->p_args = strdup(cline);
186 	ap = p->p_argv;
187 	for (s = p->p_args; s != NULL; ) {
188 		char *val;
189 		while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
190 			;
191 		if (val) {
192 			*ap++ = val;
193 			p->p_argc++;
194 		}
195 	}
196 	*ap = 0;
197 
198 #ifdef DEBUG
199 	for (c = 0; c < p->p_argc; c++)
200 		printf("%sv[%d] = %s\n", c?"\t":"", c, p->p_argv[c]);
201 #endif
202 
203 	p->p_key = p->p_argv[0];
204 	if (strpbrk(p->p_key, RE_CHARS)) {
205 		curp = p;			/* XXX */
206 		p->p_re = regcomp(p->p_key);
207 		curp = 0;			/* XXX */
208 	} else {
209 		p->p_re = 0;
210 	}
211 	p->p_lno = lno;
212 
213 	return (p);
214 }
215 
216 /*
217  * Free a path structure
218  */
219 static void pfree(p)
220 path *p;
221 {
222 	free(p->p_args);
223 	if (p->p_re)
224 		free((char *) p->p_re);
225 	free((char *) p->p_argv);
226 	free((char *) p);
227 }
228 
229 /*
230  * Discard all currently held path structures on q0.
231  * and add all the ones on xq.
232  */
233 static void preplace(q0, xq)
234 qelem *q0;
235 qelem *xq;
236 {
237 	/*
238 	 * While the list is not empty,
239 	 * take the first element off the list
240 	 * and free it.
241 	 */
242 	while (q0->q_forw != q0) {
243 		qelem *q = q0->q_forw;
244 		rem_que(q);
245 		pfree((path *) q);
246 	}
247 	while (xq->q_forw != xq) {
248 		qelem *q = xq->q_forw;
249 		rem_que(q);
250 		ins_que(q, q0);
251 	}
252 }
253 
254 /*
255  * Read the lines from the configuration file and
256  * add them to the list of paths.
257  */
258 static void readfp(q0, fp)
259 qelem *q0;
260 FILE *fp;
261 {
262 	char cline[LINE_MAX];
263 	int nread = 0;
264 	qelem q;
265 
266 	/*
267 	 * Make a new empty list.
268 	 */
269 	q.q_forw = q.q_back = &q;
270 
271 	/*
272 	 * Read the lines from the configuration file.
273 	 */
274 	while (fgets(cline, sizeof(cline), fp)) {
275 		path *p = palloc(cline, nread+1);
276 		if (p && !pinsert(p, &q))
277 			pfree(p);
278 		nread++;
279 	}
280 
281 	/*
282 	 * If some records were read, then throw
283 	 * away the old list and replace with the
284 	 * new one.
285 	 */
286 	if (nread)
287 		preplace(q0, &q);
288 }
289 
290 /*
291  * Read the configuration file (conf) and replace
292  * the existing path list with the new version.
293  * If the file is not readable, then no changes take place
294  */
295 void conf_read(q, conf)
296 qelem *q;
297 char *conf;
298 {
299 	FILE *fp = fopen(conf, "r");
300 	if (fp) {
301 		conf_file = conf;		/* XXX */
302 		readfp(q, fp);
303 		conf_file = 0;		/* XXX */
304 		(void) fclose(fp);
305 	} else {
306 		syslog(LOG_ERR, "open config file \"%s\": %s", conf, strerror(errno));
307 	}
308 }
309 
310 
311 char **conf_match(q0, key)
312 qelem *q0;
313 char *key;
314 {
315 	qelem *q;
316 
317 	for (q = q0->q_forw; q != q0; q = q->q_forw) {
318 		path *p = (path *) q;
319 		if (p->p_re) {
320 			if (regexec(p->p_re, key))
321 				return (p->p_argv+1);
322 		} else {
323 			if (strncmp(p->p_key, key, strlen(p->p_key)) == 0)
324 				return (p->p_argv+1);
325 		}
326 	}
327 
328 	return (0);
329 }
330