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