conf.c revision 1.2 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