1 /*
2 * Copyright (c) 1990 Jan-Simon Pendry
3 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
10 * %sccs.include.redist.c%
11 *
12 * @(#)info_file.c 8.1 (Berkeley) 06/06/93
13 *
14 * $Id: info_file.c,v 5.2.2.1 1992/02/09 15:08:28 jsp beta $
15 *
16 */
17
18 /*
19 * Get info from file
20 */
21
22 #include "am.h"
23
24 #ifdef HAS_FILE_MAPS
25 #include <ctype.h>
26 #include <sys/stat.h>
27
28 #define MAX_LINE_LEN 2048
29
30 static int read_line P((char *buf, int size, FILE *fp));
read_line(buf,size,fp)31 static int read_line(buf, size, fp)
32 char *buf;
33 int size;
34 FILE *fp;
35 {
36 int done = 0;
37
38 do {
39 while (fgets(buf, size, fp)) {
40 int len = strlen(buf);
41 done += len;
42 if (len > 1 && buf[len-2] == '\\' &&
43 buf[len-1] == '\n') {
44 int ch;
45 buf += len - 2;
46 size -= len - 2;
47 *buf = '\n'; buf[1] = '\0';
48 /*
49 * Skip leading white space on next line
50 */
51 while ((ch = getc(fp)) != EOF &&
52 isascii(ch) && isspace(ch))
53 ;
54 (void) ungetc(ch, fp);
55 } else {
56 return done;
57 }
58 }
59 } while (size > 0 && !feof(fp));
60
61 return done;
62 }
63
64 /*
65 * Try to locate a key in a file
66 */
67 static int search_or_reload_file P((FILE *fp, char *map, char *key, char **val, mnt_map *m, void (*fn)(mnt_map *m, char*, char*)));
search_or_reload_file(fp,map,key,val,m,fn)68 static int search_or_reload_file(fp, map, key, val, m, fn)
69 FILE *fp;
70 char *map;
71 char *key;
72 char **val;
73 mnt_map *m;
74 void (*fn) P((mnt_map*, char*, char*));
75 {
76 char key_val[MAX_LINE_LEN];
77 int chuck = 0;
78 int line_no = 0;
79
80 while (read_line(key_val, sizeof(key_val), fp)) {
81 char *kp;
82 char *cp;
83 char *hash;
84 int len = strlen(key_val);
85 line_no++;
86
87 /*
88 * Make sure we got the whole line
89 */
90 if (key_val[len-1] != '\n') {
91 plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
92 chuck = 1;
93 } else {
94 key_val[len-1] = '\0';
95 }
96
97 /*
98 * Strip comments
99 */
100 hash = strchr(key_val, '#');
101 if (hash)
102 *hash = '\0';
103
104 /*
105 * Find start of key
106 */
107 for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
108 ;
109
110 /*
111 * Ignore blank lines
112 */
113 if (!*kp)
114 goto again;
115
116 /*
117 * Find end of key
118 */
119 for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
120 ;
121
122 /*
123 * Check whether key matches
124 */
125 if (*cp)
126 *cp++ = '\0';
127
128 if (fn || (*key == *kp && strcmp(key, kp) == 0)) {
129 while (*cp && isascii(*cp) && isspace(*cp))
130 cp++;
131 if (*cp) {
132 /*
133 * Return a copy of the data
134 */
135 char *dc = strdup(cp);
136 if (fn) {
137 (*fn)(m, strdup(kp), dc);
138 } else {
139 *val = dc;
140 #ifdef DEBUG
141 dlog("%s returns %s", key, dc);
142 #endif /* DEBUG */
143 }
144 if (!fn)
145 return 0;
146 } else {
147 plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
148 }
149 }
150
151 again:
152 /*
153 * If the last read didn't get a whole line then
154 * throw away the remainder before continuing...
155 */
156 if (chuck) {
157 while (fgets(key_val, sizeof(key_val), fp) &&
158 !strchr(key_val, '\n'))
159 ;
160 chuck = 0;
161 }
162 }
163
164 return fn ? 0 : ENOENT;
165 }
166
167 static FILE *file_open P((char *map, time_t *tp));
file_open(map,tp)168 static FILE *file_open(map, tp)
169 char *map;
170 time_t *tp;
171 {
172 FILE *mapf = fopen(map, "r");
173 if (mapf && tp) {
174 struct stat stb;
175 if (fstat(fileno(mapf), &stb) < 0)
176 *tp = clocktime();
177 else
178 *tp = stb.st_mtime;
179 }
180 return mapf;
181 }
182
183 int file_init P((char *map, time_t *tp));
file_init(map,tp)184 int file_init(map, tp)
185 char *map;
186 time_t *tp;
187 {
188 FILE *mapf = file_open(map, tp);
189 if (mapf) {
190 (void) fclose(mapf);
191 return 0;
192 }
193 return errno;
194 }
195
196 int file_reload P((mnt_map *m, char *map, void (*fn)()));
file_reload(m,map,fn)197 int file_reload(m, map, fn)
198 mnt_map *m;
199 char *map;
200 void (*fn)();
201 {
202 FILE *mapf = file_open(map, (time_t *) 0);
203 if (mapf) {
204 int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
205 (void) fclose(mapf);
206 return error;
207 }
208
209 return errno;
210 }
211
212 int file_search P((mnt_map *m, char *map, char *key, char **pval, time_t *tp));
file_search(m,map,key,pval,tp)213 int file_search(m, map, key, pval, tp)
214 mnt_map *m;
215 char *map;
216 char *key;
217 char **pval;
218 time_t *tp;
219 {
220 time_t t;
221 FILE *mapf = file_open(map, &t);
222 if (mapf) {
223 int error;
224 if (*tp < t) {
225 *tp = t;
226 error = -1;
227 } else {
228 error = search_or_reload_file(mapf, map, key, pval, 0, 0);
229 }
230 (void) fclose(mapf);
231 return error;
232 }
233
234 return errno;
235 }
236
237 int file_mtime P((char *map, time_t *tp));
file_mtime(map,tp)238 int file_mtime(map, tp)
239 char *map;
240 time_t *tp;
241 {
242 FILE *mapf = file_open(map, tp);
243 if (mapf) {
244 (void) fclose(mapf);
245 return 0;
246 }
247
248 return errno;
249 }
250 #endif /* HAS_FILE_MAPS */
251