1 /* 2 * Copyright (c) 1989, 1993 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.7 (Berkeley) 01/03/94"; 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 101 /* 102 * addlist -- 103 * Add a tag to the list. 104 */ 105 TAG * 106 addlist(name) 107 char *name; 108 { 109 TAG *tp; 110 111 if ((tp = calloc(1, sizeof(TAG))) == NULL || 112 (tp->s = strdup(name)) == NULL) 113 err(1, NULL); 114 TAILQ_INIT(&tp->list); 115 TAILQ_INSERT_TAIL(&head, tp, q); 116 return (tp); 117 } 118 119 /* 120 * getlist -- 121 * Return the linked list of entries for a tag if it exists. 122 */ 123 TAG * 124 getlist(name) 125 char *name; 126 { 127 TAG *tp; 128 129 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) 130 if (!strcmp(name, tp->s)) 131 return (tp); 132 return (NULL); 133 } 134 135 void 136 debug(l) 137 char *l; 138 { 139 TAG *tp; 140 ENTRY *ep; 141 142 (void)printf("%s ===============\n", l); 143 for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) { 144 printf("%s\n", tp->s); 145 for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next) 146 printf("\t%s\n", ep->s); 147 } 148 } 149