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