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