 |
|
|
| |
1 /*
2 * Copyright (c) 1997-2005 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *
40 * File: am-utils/amd/info_file.c
41 *
42 */
43
44 /*
45 * Get info from file
46 */
47
48 #ifdef HAVE_CONFIG_H
49 # include <config.h>
50 #endif /* HAVE_CONFIG_H */
51 #include <am_defs.h>
52 #include <amd.h>
53
54 #define MAX_LINE_LEN 1500
55
56 /* forward declarations */
57 int file_init_or_mtime(mnt_map *m, char *map, time_t *tp);
58 int file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *));
59 int file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
60
61
62 static int
63 read_line(char *buf, int size, FILE *fp)
64 {
65 int done = 0;
66
67 do {
68 while (fgets(buf, size, fp)) {
69 int len = strlen(buf);
70 done += len;
71 if (len > 1 && buf[len - 2] == '\\' &&
72 buf[len - 1] == '\n') {
73 int ch;
74 buf += len - 2;
75 size -= len - 2;
76 *buf = '\n';
77 buf[1] = '\0';
78 /*
79 * Skip leading white space on next line
80 */
81 while ((ch = getc(fp)) != EOF &&
82 isascii(ch) && isspace(ch)) ;
83 (void) ungetc(ch, fp);
84 } else {
85 return done;
86 }
87 }
88 } while (size > 0 && !feof(fp) && !ferror(fp));
89
90 return done;
91 }
92
93
94 /*
95 * Try to locate a key in a file
96 */
97 static int
98 file_search_or_reload(FILE *fp,
99 char *map,
100 char *key,
101 char **val,
102 mnt_map *m,
103 void (*fn) (mnt_map *m, char *, char *))
104 {
105 char key_val[MAX_LINE_LEN];
106 int chuck = 0;
107 int line_no = 0;
108
109 while (read_line(key_val, sizeof(key_val), fp)) {
110 char *kp;
111 char *cp;
112 char *hash;
113 int len = strlen(key_val);
114 line_no++;
115
116 /*
117 * Make sure we got the whole line
118 */
119 if (key_val[len - 1] != '\n') {
120 plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
121 chuck = 1;
122 } else {
123 key_val[len - 1] = '\0';
124 }
125
126 /*
127 * Strip comments
128 */
129 hash = strchr(key_val, '#');
130 if (hash)
131 *hash = '\0';
132
133 /*
134 * Find start of key
135 */
136 for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
137
138 /*
139 * Ignore blank lines
140 */
141 if (!*kp)
142 goto again;
143
144 /*
145 * Find end of key
146 */
147 for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
148
149 /*
150 * Check whether key matches
151 */
152 if (*cp)
153 *cp++ = '\0';
154
155 if (fn || (*key == *kp && STREQ(key, kp))) {
156 while (*cp && isascii(*cp) && isspace((int)*cp))
157 cp++;
158 if (*cp) {
159 /*
160 * Return a copy of the data
161 */
162 char *dc = strdup(cp);
163 if (fn) {
164 (*fn) (m, strdup(kp), dc);
165 } else {
166 *val = dc;
167 dlog("%s returns %s", key, dc);
168 }
169 if (!fn)
170 return 0;
171 } else {
172 plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
173 }
174 }
175
176 again:
177 /*
178 * If the last read didn't get a whole line then
179 * throw away the remainder before continuing...
180 */
181 if (chuck) {
182 while (fgets(key_val, sizeof(key_val), fp) &&
183 !strchr(key_val, '\n')) ;
184 chuck = 0;
185 }
186 }
187
188 return fn ? 0 : ENOENT;
189 }
190
191
192 static FILE *
193 file_open(char *map, time_t *tp)
194 {
195 FILE *mapf = fopen(map, "r");
196
197 if (mapf && tp) {
198 struct stat stb;
199 if (fstat(fileno(mapf), &stb) < 0)
200 *tp = clocktime();
201 else
202 *tp = stb.st_mtime;
203 }
204 return mapf;
205 }
206
207
208 int
209 file_init_or_mtime(mnt_map *m, char *map, time_t *tp)
210 {
211 FILE *mapf = file_open(map, tp);
212
213 if (mapf) {
214 fclose(mapf);
215 return 0;
216 }
217 return errno;
218 }
219
220
221 int
222 file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *))
223 {
224 FILE *mapf = file_open(map, (time_t *) 0);
225
226 if (mapf) {
227 int error = file_search_or_reload(mapf, map, 0, 0, m, fn);
228 (void) fclose(mapf);
229 return error;
230 }
231 return errno;
232 }
233
234
235 int
236 file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
237 {
238 time_t t;
239 FILE *mapf = file_open(map, &t);
240
241 if (mapf) {
242 int error;
243 if (*tp < t) {
244 *tp = t;
245 error = -1;
246 } else {
247 error = file_search_or_reload(mapf, map, key, pval, 0, 0);
248 }
249 (void) fclose(mapf);
250 return error;
251 }
252 return errno;
253 }
254