Commit | Line | Data |
---|---|---|
1ef31675 | 1 | /* |
00186a84 KB |
2 | * Copyright (c) 1989, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
1ef31675 | 4 | * |
f15db449 | 5 | * %sccs.include.redist.c% |
1ef31675 KB |
6 | */ |
7 | ||
8 | #ifndef lint | |
97231dd4 | 9 | static char sccsid[] = "@(#)config.c 8.6 (Berkeley) %G%"; |
1ef31675 KB |
10 | #endif /* not lint */ |
11 | ||
da0c0e56 KB |
12 | #include <sys/types.h> |
13 | #include <sys/queue.h> | |
14 | ||
15 | #include <ctype.h> | |
16 | #include <err.h> | |
1ef31675 | 17 | #include <errno.h> |
da0c0e56 | 18 | #include <stdio.h> |
011519cd | 19 | #include <stdlib.h> |
da0c0e56 | 20 | #include <string.h> |
011519cd | 21 | |
da0c0e56 KB |
22 | #include "config.h" |
23 | #include "pathnames.h" | |
1ef31675 | 24 | |
c46750de | 25 | struct _head head; |
011519cd | 26 | |
1ef31675 | 27 | /* |
da0c0e56 KB |
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 | |
1ef31675 | 36 | */ |
da0c0e56 | 37 | void |
7d9403e1 KB |
38 | config(fname) |
39 | char *fname; | |
1ef31675 | 40 | { |
c46750de KB |
41 | TAG *tp; |
42 | ENTRY *ep; | |
da0c0e56 | 43 | FILE *cfp; |
011519cd | 44 | size_t len; |
da0c0e56 KB |
45 | int lcnt; |
46 | char *p, *t; | |
47 | ||
7d9403e1 KB |
48 | if (fname == NULL) |
49 | fname = _PATH_MANCONF; | |
50 | if ((cfp = fopen(fname, "r")) == NULL) | |
51 | err(1, "%s", fname); | |
c46750de | 52 | TAILQ_INIT(&head); |
da0c0e56 | 53 | for (lcnt = 1; (p = fgetline(cfp, &len)) != NULL; ++lcnt) { |
97231dd4 | 54 | if (len == 1) /* Skip empty lines. */ |
da0c0e56 KB |
55 | continue; |
56 | if (p[len - 1] != '\n') { /* Skip corrupted lines. */ | |
7d9403e1 | 57 | warnx("%s: line %d corrupted", fname, lcnt); |
da0c0e56 | 58 | continue; |
011519cd | 59 | } |
da0c0e56 KB |
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 == '#') | |
011519cd | 66 | continue; |
da0c0e56 KB |
67 | /* Find first token. */ |
68 | for (t = p; *t && !isspace(*t); ++t); | |
69 | if (*t == '\0') /* Need more than one token.*/ | |
011519cd | 70 | continue; |
da0c0e56 KB |
71 | *t = '\0'; |
72 | ||
c46750de KB |
73 | for (tp = head.tqh_first; /* Find any matching tag. */ |
74 | tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next); | |
da0c0e56 | 75 | |
c46750de KB |
76 | if (tp == NULL) /* Create a new tag. */ |
77 | tp = addlist(p); | |
da0c0e56 KB |
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); | |
c46750de | 91 | TAILQ_INSERT_TAIL(&tp->list, ep, q); |
18cef530 | 92 | } else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) { |
da0c0e56 KB |
93 | if ((ep = malloc(sizeof(ENTRY))) == NULL || |
94 | (ep->s = strdup(p)) == NULL) | |
95 | err(1, NULL); | |
c46750de | 96 | TAILQ_INSERT_TAIL(&tp->list, ep, q); |
011519cd KB |
97 | } |
98 | } | |
011519cd | 99 | } |
1ef31675 | 100 | |
da0c0e56 KB |
101 | /* |
102 | * addlist -- | |
103 | * Add a tag to the list. | |
104 | */ | |
c46750de | 105 | TAG * |
da0c0e56 KB |
106 | addlist(name) |
107 | char *name; | |
011519cd | 108 | { |
c46750de | 109 | TAG *tp; |
da0c0e56 | 110 | |
c46750de KB |
111 | if ((tp = calloc(1, sizeof(TAG))) == NULL || |
112 | (tp->s = strdup(name)) == NULL) | |
da0c0e56 | 113 | err(1, NULL); |
c46750de KB |
114 | TAILQ_INIT(&tp->list); |
115 | TAILQ_INSERT_TAIL(&head, tp, q); | |
116 | return (tp); | |
011519cd KB |
117 | } |
118 | ||
da0c0e56 KB |
119 | /* |
120 | * getlist -- | |
c46750de | 121 | * Return the linked list of entries for a tag if it exists. |
da0c0e56 | 122 | */ |
c46750de | 123 | TAG * |
da0c0e56 KB |
124 | getlist(name) |
125 | char *name; | |
011519cd | 126 | { |
c46750de | 127 | TAG *tp; |
011519cd | 128 | |
c46750de KB |
129 | for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) |
130 | if (!strcmp(name, tp->s)) | |
131 | return (tp); | |
da0c0e56 | 132 | return (NULL); |
1ef31675 KB |
133 | } |
134 | ||
da0c0e56 KB |
135 | void |
136 | debug(l) | |
137 | char *l; | |
011519cd | 138 | { |
c46750de KB |
139 | TAG *tp; |
140 | ENTRY *ep; | |
011519cd | 141 | |
da0c0e56 | 142 | (void)printf("%s ===============\n", l); |
c46750de KB |
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) | |
da0c0e56 | 146 | printf("\t%s\n", ep->s); |
011519cd | 147 | } |
1ef31675 | 148 | } |