1 /* $NetBSD: manconf.c,v 1.4 2003/10/27 00:12:43 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 1/31/95"; 40 #else 41 __RCSID("$NetBSD: manconf.c,v 1.4 2003/10/27 00:12:43 lukem Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/types.h> 46 #include <sys/queue.h> 47 48 #include <ctype.h> 49 #include <err.h> 50 #include <errno.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 55 #include "manconf.h" 56 #include "pathnames.h" 57 58 struct _head head; 59 60 /* 61 * config -- 62 * 63 * Read the configuration file and build a doubly linked 64 * list that looks like: 65 * 66 * tag1 <-> record <-> record <-> record 67 * | 68 * tag2 <-> record <-> record <-> record 69 */ 70 void 71 config(fname) 72 const char *fname; 73 { 74 TAG *tp; 75 FILE *cfp; 76 size_t len; 77 int lcnt; 78 char *p, *t, type; 79 80 if (fname == NULL) 81 fname = _PATH_MANCONF; 82 if ((cfp = fopen(fname, "r")) == NULL) 83 err(1, "%s", fname); 84 TAILQ_INIT(&head); 85 for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) { 86 if (len == 1) /* Skip empty lines. */ 87 continue; 88 if (p[len - 1] != '\n') { /* Skip corrupted lines. */ 89 warnx("%s: line %d corrupted", fname, lcnt); 90 continue; 91 } 92 p[len - 1] = '\0'; /* Terminate the line. */ 93 94 /* Skip leading space. */ 95 for (; *p != '\0' && isspace((unsigned char)*p); ++p); 96 /* Skip empty/comment lines. */ 97 if (*p == '\0' || *p == '#') 98 continue; 99 /* Find first token. */ 100 for (t = p; *t && !isspace((unsigned char)*t); ++t); 101 if (*t == '\0') /* Need more than one token.*/ 102 continue; 103 *t = '\0'; 104 105 tp = getlist(p, 1); 106 107 /* 108 * Attach new records. Check to see if it is a 109 * section record or not. 110 */ 111 112 if (*p == '_') { /* not a section record */ 113 /* 114 * Special cases: _build and _crunch take the 115 * rest of the line as a single entry. 116 */ 117 if (!strcmp(p, "_build") || !strcmp(p, "_crunch")) { 118 /* 119 * The reason we're not just using 120 * strtok(3) for all of the parsing is 121 * so we don't get caught if a line 122 * has only a single token on it. 123 */ 124 while (*++t && isspace((unsigned char)*t)); 125 addentry(tp, t, 0); 126 } else { 127 for(++t; (p = strtok(t, " \t\n")) != NULL; 128 t = NULL) 129 addentry(tp, p, 0); 130 } 131 132 } else { /* section record */ 133 134 /* 135 * section entries can either be all absolute 136 * paths or all relative paths, but not both. 137 */ 138 type = (TAILQ_FIRST(&tp->list) != NULL) ? 139 *(TAILQ_FIRST(&tp->list)->s) : 0; 140 141 for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) { 142 143 /* ensure an assigned type */ 144 if (type == 0) 145 type = *p; 146 147 /* check for illegal mix */ 148 if (*p != type) { 149 warnx("section %s: %s: invalid entry, does not match previous types", 150 tp->s, p); 151 warnx("man.conf cannot mix absolute and relative paths in an entry"); 152 continue; 153 } 154 addentry(tp, p, 0); 155 } 156 } 157 } 158 159 fclose(cfp); 160 } 161 162 /* 163 * getlist -- 164 * Return the linked list of entries for a tag if it exists. 165 * If it doesn't exist and create is non zero, create new tag 166 * and return that, otherwise return NULL. 167 */ 168 TAG * 169 getlist(name, create) 170 const char *name; 171 int create; 172 { 173 TAG *tp; 174 175 TAILQ_FOREACH(tp, &head, q) 176 if (!strcmp(name, tp->s)) 177 return (tp); 178 if (create) { 179 if ((tp = malloc(sizeof(TAG))) == NULL || 180 (tp->s = strdup(name)) == NULL) 181 err(1, "malloc"); 182 TAILQ_INIT(&tp->list); 183 TAILQ_INSERT_TAIL(&head, tp, q); 184 return (tp); 185 } else 186 return (NULL); 187 } 188 189 /* 190 * addentry -- 191 * add an entry to a list. 192 */ 193 void 194 addentry(tp, newent, head) 195 TAG *tp; 196 const char *newent; 197 int head; 198 { 199 ENTRY *ep; 200 201 if ((ep = malloc(sizeof(*ep))) == NULL || 202 (ep->s = strdup(newent)) == NULL) 203 err(1, "malloc"); 204 if (head) 205 TAILQ_INSERT_HEAD(&tp->list, ep, q); 206 else 207 TAILQ_INSERT_TAIL(&tp->list, ep, q); 208 } 209 210 #ifdef MANDEBUG 211 void 212 debug(l) 213 const char *l; 214 { 215 TAG *tp; 216 ENTRY *ep; 217 218 (void)printf("%s ===============\n", l); 219 TAILQ_FOREACH(tp, &head, q) { 220 printf("%s\n", tp->s); 221 TAILQ_FOREACH(ep, &tp->list, q) 222 printf("\t%s\n", ep->s); 223 } 224 } 225 #endif 226