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