xref: /original-bsd/usr.sbin/amd/amd/info_file.c (revision c3e32dec)
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));
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*)));
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));
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));
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)()));
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));
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));
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