1 /* 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)config.c 8.8 (Berkeley) 01/31/95"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <sys/queue.h> 14 15 #include <ctype.h> 16 #include <err.h> 17 #include <errno.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include "config.h" 23 #include "pathnames.h" 24 25 struct _head head; 26 27 /* 28 * config -- 29 * 30 * Read the configuration file and build a doubly linked 31 * list that looks like: 32 * 33 * tag1 <-> record <-> record <-> record 34 * | 35 * tag2 <-> record <-> record <-> record 36 */ 37 void 38 config(fname) 39 char *fname; 40 { 41 TAG *tp; 42 ENTRY *ep; 43 FILE *cfp; 44 size_t len; 45 int lcnt; 46 char *p, *t; 47 48 if (fname == NULL) 49 fname = _PATH_MANCONF; 50 if ((cfp = fopen(fname, "r")) == NULL) 51 err(1, "%s", fname); 52 TAILQ_INIT(&head); 53 for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) { 54 if (len == 1) /* Skip empty lines. */ 55 continue; 56 if (p[len - 1] != '\n') { /* Skip corrupted lines. */ 57 warnx("%s: line %d corrupted", fname, lcnt); 58 continue; 59 } 60 p[len - 1] = '\0'; /* Terminate the line. */ 61 62 /* Skip leading space. */ 63 for (; *p != '\0' && isspace(*p); ++p); 64 /* Skip empty/comment lines. */ 65 if (*p == '\0' || *p == '#') 66 continue; 67 /* Find first token. */ 68 for (t = p; *t && !isspace(*t); ++t); 69 if (*t == '\0') /* Need more than one token.*/ 70 continue; 71 *t = '\0'; 72 73 for (tp = head.tqh_first; /* Find any matching tag. */ 74 tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next); 75 76 if (tp == NULL) /* Create a new tag. */ 77 tp = addlist(p); 78 79 /* 80 * Attach new records. The keyword _build takes the rest of 81 * the line as a single entity, everything else is white 82 * space separated. The reason we're not just using strtok(3) 83 * for all of the parsing is so we don't get caught if a line 84 * has only a single token on it. 85 */ 86 if (!strcmp(p, "_build")) { 87 while (*++t && isspace(*t)); 88 if ((ep = malloc(sizeof(ENTRY))) == NULL || 89 (ep->s = strdup(t)) == NULL) 90 err(1, NULL); 91 TAILQ_INSERT_TAIL(&tp->list, ep, q); 92 } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) { 93 if ((ep = malloc(sizeof(ENTRY))) == NULL || 94 (ep->s = strdup(p)) == NULL) 95 err(1, NULL); 96 TAILQ_INSERT_TAIL(&tp->list, ep, q); 97 } 98 } 99 100 fclose(cfp); 101 } 102 103 /* 104 * addlist -- 105 * Add a tag to the list. 106 */ 107 TAG * 108 addlist(name) 109 char *name; 110 { 111 TAG *tp; 112 113 if ((tp = calloc(1, sizeof(TAG))) == NULL || 114 (tp->s = strdup(name)) == NULL) 115 err(1, NULL); 116 TAILQ_INIT(&tp->list); 117 TAILQ_INSERT_TAIL(&head, tp, q); 118 return (tp); 119 } 120 121 /* 122 * getlist -- 123 * Return the linked list of entries for a tag if it exists. 124 */ 125 TAG * 126 getlist(name) 127 char *name; 128 { 129 TAG *tp; 130 131 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) 132 if (!strcmp(name, tp->s)) 133 return (tp); 134 return (NULL); 135 } 136 137 void 138 debug(l) 139 char *l; 140 { 141 TAG *tp; 142 ENTRY *ep; 143 144 (void)printf("%s ===============\n", l); 145 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) { 146 printf("%s\n", tp->s); 147 for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next) 148 printf("\t%s\n", ep->s); 149 } 150 } 151