154851Spendry /*
261515Sbostic * Copyright (c) 1992, 1993
361515Sbostic * The Regents of the University of California. All rights reserved.
454851Spendry * All rights reserved.
554851Spendry *
654851Spendry * This code is derived from software donated to Berkeley by
754851Spendry * Jan-Simon Pendry.
854851Spendry *
954851Spendry * %sccs.include.redist.c%
1054851Spendry *
11*66484Spendry * @(#)conf.c 8.2 (Berkeley) 03/27/94
1254851Spendry *
1354851Spendry * $Id: conf.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $
1454851Spendry */
1554851Spendry
1654851Spendry #include <stdio.h>
1754851Spendry #include <stdlib.h>
1854851Spendry #include <unistd.h>
1954851Spendry #include <string.h>
2054851Spendry #include <errno.h>
2154851Spendry #include <limits.h>
2254851Spendry #include <regexp.h>
2354851Spendry #include <sys/types.h>
2454979Spendry #include <sys/param.h>
2554851Spendry #include <sys/syslog.h>
2654851Spendry
2754851Spendry #include "portald.h"
2854851Spendry
2954851Spendry #define ALLOC(ty) (xmalloc(sizeof(ty)))
3054851Spendry
3154851Spendry typedef struct path path;
3254851Spendry struct path {
3354851Spendry qelem p_q; /* 2-way linked list */
3454851Spendry int p_lno; /* Line number of this record */
3554851Spendry char *p_args; /* copy of arg string (malloc) */
3654851Spendry char *p_key; /* Pathname to match (also p_argv[0]) */
3754851Spendry regexp *p_re; /* RE to match against pathname (malloc) */
3854851Spendry int p_argc; /* number of elements in arg string */
3954851Spendry char **p_argv; /* argv[] pointers into arg string (malloc) */
4054851Spendry };
4154851Spendry
4254851Spendry static char *conf_file; /* XXX for regerror */
4354851Spendry static path *curp; /* XXX for regerror */
4454851Spendry
4554851Spendry /*
4654851Spendry * Add an element to a 2-way list,
4754851Spendry * just after (pred)
4854851Spendry */
ins_que(elem,pred)4954851Spendry static void ins_que(elem, pred)
5054851Spendry qelem *elem, *pred;
5154851Spendry {
5254851Spendry qelem *p = pred->q_forw;
5354851Spendry elem->q_back = pred;
5454851Spendry elem->q_forw = p;
5554851Spendry pred->q_forw = elem;
5654851Spendry p->q_back = elem;
5754851Spendry }
5854851Spendry
5954851Spendry /*
6054851Spendry * Remove an element from a 2-way list
6154851Spendry */
rem_que(elem)6254851Spendry static void rem_que(elem)
6354851Spendry qelem *elem;
6454851Spendry {
6554851Spendry qelem *p = elem->q_forw;
6654851Spendry qelem *p2 = elem->q_back;
6754851Spendry p2->q_forw = p;
6854851Spendry p->q_back = p2;
6954851Spendry }
7054851Spendry
7154851Spendry /*
7254851Spendry * Error checking malloc
7354851Spendry */
xmalloc(siz)7454851Spendry static void *xmalloc(siz)
7554851Spendry unsigned siz;
7654851Spendry {
7754851Spendry void *p = malloc(siz);
7854851Spendry if (p)
7954851Spendry return (p);
8054851Spendry syslog(LOG_ALERT, "malloc: failed to get %d bytes", siz);
8154851Spendry exit(1);
8254851Spendry }
8354851Spendry
8454851Spendry /*
8554851Spendry * Insert the path in the list.
8654851Spendry * If there is already an element with the same key then
8754851Spendry * the *second* one is ignored (return 0). If the key is
8854851Spendry * not found then the path is added to the end of the list
8954851Spendry * and 1 is returned.
9054851Spendry */
pinsert(p0,q0)9154851Spendry static int pinsert(p0, q0)
9254851Spendry path *p0;
9354851Spendry qelem *q0;
9454851Spendry {
9554851Spendry qelem *q;
9654851Spendry
9754851Spendry if (p0->p_argc == 0)
9854851Spendry return (0);
9954851Spendry
10054851Spendry for (q = q0->q_forw; q != q0; q = q->q_forw) {
10154851Spendry path *p = (path *) q;
10254851Spendry if (strcmp(p->p_key, p0->p_key) == 0)
10354851Spendry return (0);
10454851Spendry }
10554851Spendry ins_que(&p0->p_q, q0->q_back);
10654851Spendry return (1);
10754851Spendry
10854851Spendry }
10954851Spendry
regerror(s)11054851Spendry void regerror(s)
11154851Spendry const char *s;
11254851Spendry {
11354851Spendry syslog(LOG_ERR, "%s:%s: regcomp %s: %s",
11454851Spendry conf_file, curp->p_lno, curp->p_key, s);
11554851Spendry }
11654851Spendry
palloc(cline,lno)11754851Spendry static path *palloc(cline, lno)
11854851Spendry char *cline;
11954851Spendry int lno;
12054851Spendry {
12154851Spendry int c;
12254851Spendry char *s;
12354851Spendry char *key;
12454851Spendry path *p;
12554851Spendry char **ap;
12654851Spendry
12754851Spendry /*
12854851Spendry * Implement comment chars
12954851Spendry */
13054851Spendry s = strchr(cline, '#');
13154851Spendry if (s)
13254851Spendry *s = 0;
13354851Spendry
13454851Spendry /*
13554851Spendry * Do a pass through the string to count the number
13654851Spendry * of arguments
13754851Spendry */
13854851Spendry c = 0;
13954851Spendry key = strdup(cline);
14054851Spendry for (s = key; s != NULL; ) {
14154851Spendry char *val;
14254851Spendry while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
14354851Spendry ;
14454851Spendry if (val)
14554851Spendry c++;
14654851Spendry }
14754851Spendry c++;
14854851Spendry free(key);
14954851Spendry
15054851Spendry if (c <= 1)
15154851Spendry return (0);
15254851Spendry
15354851Spendry /*
15454851Spendry * Now do another pass and generate a new path structure
15554851Spendry */
15654851Spendry p = ALLOC(path);
15754851Spendry p->p_argc = 0;
15854851Spendry p->p_argv = xmalloc(c * sizeof(char *));
15954851Spendry p->p_args = strdup(cline);
16054851Spendry ap = p->p_argv;
16154851Spendry for (s = p->p_args; s != NULL; ) {
16254851Spendry char *val;
16354851Spendry while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
16454851Spendry ;
16554851Spendry if (val) {
16654851Spendry *ap++ = val;
16754851Spendry p->p_argc++;
16854851Spendry }
16954851Spendry }
17054851Spendry *ap = 0;
17154851Spendry
17254851Spendry #ifdef DEBUG
17354851Spendry for (c = 0; c < p->p_argc; c++)
17454851Spendry printf("%sv[%d] = %s\n", c?"\t":"", c, p->p_argv[c]);
17554851Spendry #endif
17654851Spendry
17754851Spendry p->p_key = p->p_argv[0];
17854851Spendry if (strpbrk(p->p_key, RE_CHARS)) {
17954851Spendry curp = p; /* XXX */
18054851Spendry p->p_re = regcomp(p->p_key);
18154851Spendry curp = 0; /* XXX */
18254851Spendry } else {
18354851Spendry p->p_re = 0;
18454851Spendry }
18554851Spendry p->p_lno = lno;
18654851Spendry
18754851Spendry return (p);
18854851Spendry }
18954851Spendry
19054851Spendry /*
19154851Spendry * Free a path structure
19254851Spendry */
pfree(p)19354851Spendry static void pfree(p)
19454851Spendry path *p;
19554851Spendry {
19654851Spendry free(p->p_args);
19754851Spendry if (p->p_re)
19854851Spendry free((char *) p->p_re);
19954851Spendry free((char *) p->p_argv);
20054851Spendry free((char *) p);
20154851Spendry }
20254851Spendry
20354851Spendry /*
20454851Spendry * Discard all currently held path structures on q0.
20554851Spendry * and add all the ones on xq.
20654851Spendry */
preplace(q0,xq)20754851Spendry static void preplace(q0, xq)
20854851Spendry qelem *q0;
20954851Spendry qelem *xq;
21054851Spendry {
21154851Spendry /*
21254851Spendry * While the list is not empty,
21354851Spendry * take the first element off the list
21454851Spendry * and free it.
21554851Spendry */
21654851Spendry while (q0->q_forw != q0) {
217*66484Spendry qelem *q = q0->q_forw;
21854851Spendry rem_que(q);
21954851Spendry pfree((path *) q);
22054851Spendry }
22154851Spendry while (xq->q_forw != xq) {
22254851Spendry qelem *q = xq->q_forw;
22354851Spendry rem_que(q);
22454851Spendry ins_que(q, q0);
22554851Spendry }
22654851Spendry }
22754851Spendry
22854851Spendry /*
22954851Spendry * Read the lines from the configuration file and
23054851Spendry * add them to the list of paths.
23154851Spendry */
readfp(q0,fp)23254851Spendry static void readfp(q0, fp)
23354851Spendry qelem *q0;
23454851Spendry FILE *fp;
23554851Spendry {
23654851Spendry char cline[LINE_MAX];
23754851Spendry int nread = 0;
23854851Spendry qelem q;
23954851Spendry
24054851Spendry /*
24154851Spendry * Make a new empty list.
24254851Spendry */
24354851Spendry q.q_forw = q.q_back = &q;
24454851Spendry
24554851Spendry /*
24654851Spendry * Read the lines from the configuration file.
24754851Spendry */
24854851Spendry while (fgets(cline, sizeof(cline), fp)) {
24954851Spendry path *p = palloc(cline, nread+1);
25054851Spendry if (p && !pinsert(p, &q))
25154851Spendry pfree(p);
25254851Spendry nread++;
25354851Spendry }
25454851Spendry
25554851Spendry /*
25654851Spendry * If some records were read, then throw
25754851Spendry * away the old list and replace with the
25854851Spendry * new one.
25954851Spendry */
26054851Spendry if (nread)
26154851Spendry preplace(q0, &q);
26254851Spendry }
26354851Spendry
26454851Spendry /*
26554851Spendry * Read the configuration file (conf) and replace
26654851Spendry * the existing path list with the new version.
26754851Spendry * If the file is not readable, then no changes take place
26854851Spendry */
conf_read(q,conf)26954851Spendry void conf_read(q, conf)
27054851Spendry qelem *q;
27154851Spendry char *conf;
27254851Spendry {
27354851Spendry FILE *fp = fopen(conf, "r");
27454851Spendry if (fp) {
27554851Spendry conf_file = conf; /* XXX */
27654851Spendry readfp(q, fp);
27754851Spendry conf_file = 0; /* XXX */
27854851Spendry (void) fclose(fp);
27954851Spendry } else {
28054851Spendry syslog(LOG_ERR, "open config file \"%s\": %s", conf, strerror(errno));
28154851Spendry }
28254851Spendry }
28354851Spendry
28454851Spendry
conf_match(q0,key)28554851Spendry char **conf_match(q0, key)
28654851Spendry qelem *q0;
28754851Spendry char *key;
28854851Spendry {
28954851Spendry qelem *q;
29054851Spendry
29154851Spendry for (q = q0->q_forw; q != q0; q = q->q_forw) {
29254851Spendry path *p = (path *) q;
29354851Spendry if (p->p_re) {
29454851Spendry if (regexec(p->p_re, key))
29554851Spendry return (p->p_argv+1);
29654851Spendry } else {
29754851Spendry if (strncmp(p->p_key, key, strlen(p->p_key)) == 0)
29854851Spendry return (p->p_argv+1);
29954851Spendry }
30054851Spendry }
30154851Spendry
30254851Spendry return (0);
30354851Spendry }
304