xref: /original-bsd/usr.sbin/amd/amd/info_file.c (revision 92ab646d)
1 /*
2  * $Id: info_file.c,v 5.2 90/06/23 22:19:29 jsp Rel $
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.1 (Berkeley) 06/29/90
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(buf, size, fp)
30 char *buf;
31 int size;
32 FILE *fp;
33 {
34 	int done = 0;
35 
36 	do {
37 		while (fgets(buf, size, fp)) {
38 			int len = strlen(buf);
39 			done += len;
40 			if (len > 1 && buf[len-2] == '\\' &&
41 					buf[len-1] == '\n') {
42 				int ch;
43 				buf += len - 2;
44 				size -= len - 2;
45 				/*
46 				 * Skip leading white space on next line
47 				 */
48 				while ((ch = getc(fp)) != EOF &&
49 					isascii(ch) && isspace(ch))
50 						;
51 				(void) ungetc(ch, fp);
52 			} else {
53 				return done;
54 			}
55 		}
56 	} while (size > 0 && !feof(fp));
57 
58 	return done;
59 }
60 
61 /*
62  * Try to locate a key in a file
63  */
64 static int search_or_reload_file(fp, map, key, val, m, fn)
65 FILE *fp;
66 char *map;
67 char *key;
68 char **val;
69 mnt_map *m;
70 void (*fn) P((mnt_map*, char*, char*));
71 {
72 	char key_val[MAX_LINE_LEN];
73 	int chuck = 0;
74 	int line_no = 0;
75 
76 	while (read_line(key_val, sizeof(key_val), fp)) {
77 		char *kp;
78 		char *cp;
79 		char *hash;
80 		int len = strlen(key_val);
81 		line_no++;
82 
83 		/*
84 		 * Make sure we got the whole line
85 		 */
86 		if (key_val[len-1] != '\n') {
87 			plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map);
88 			chuck = 1;
89 		} else {
90 			key_val[len-1] = '\0';
91 		}
92 
93 		/*
94 		 * Strip comments
95 		 */
96 		hash = strchr(key_val, '#');
97 		if (hash)
98 			*hash = '\0';
99 
100 		/*
101 		 * Find start of key
102 		 */
103 		for (kp = key_val; *kp && isascii(*kp) && isspace(*kp); kp++)
104 			;
105 
106 		/*
107 		 * Ignore blank lines
108 		 */
109 		if (!*kp)
110 			goto again;
111 
112 		/*
113 		 * Find end of key
114 		 */
115 		for (cp = kp; *cp&&(!isascii(*cp)||!isspace(*cp)); cp++)
116 			;
117 
118 		/*
119 		 * Check whether key matches
120 		 */
121 		if (*cp)
122 			*cp++ = '\0';
123 
124 		if ((*key == *kp && strcmp(key, kp) == 0) || fn) {
125 			while (*cp && isascii(*cp) && isspace(*cp))
126 				cp++;
127 			if (*cp) {
128 				/*
129 				 * Return a copy of the data
130 				 */
131 				char *dc = strdup(cp);
132 				if (fn)
133 					(*fn)(m, kp, dc);
134 				else
135 					*val = dc;
136 #ifdef DEBUG
137 				dlog("%s returns %s", key, dc);
138 #endif /* DEBUG */
139 				if (!fn)
140 					return 0;
141 			} else {
142 				plog(XLOG_USER, "%s: line %d has no value field", map, line_no);
143 			}
144 		}
145 
146 again:
147 		/*
148 		 * If the last read didn't get a whole line then
149 		 * throw away the remainder before continuing...
150 		 */
151 		if (chuck) {
152 			while (fgets(key_val, sizeof(key_val), fp) &&
153 				!strchr(key_val, '\n'))
154 					;
155 			chuck = 0;
156 		}
157 	}
158 
159 	return fn ? 0 : ENOENT;
160 }
161 
162 int file_init(map)
163 char *map;
164 {
165 	FILE *mapf = fopen(map, "r");
166 	if (mapf) {
167 		(void) fclose(mapf);
168 		return 0;
169 	}
170 	return errno;
171 }
172 
173 int file_reload(m, map, fn)
174 mnt_map *m;
175 char *map;
176 void (*fn)();
177 {
178 	FILE *mapf = fopen(map, "r");
179 	if (mapf) {
180 		int error = search_or_reload_file(mapf, map, 0, 0, m, fn);
181 		(void) fclose(mapf);
182 		return error;
183 	}
184 
185 	return errno;
186 }
187 
188 int file_search(m, map, key, pval, tp)
189 mnt_map *m;
190 char *map;
191 char *key;
192 char **pval;
193 time_t *tp;
194 {
195 	FILE *mapf = fopen(map, "r");
196 	if (mapf) {
197 		struct stat stb;
198 		int error;
199 		error = fstat(fileno(mapf), &stb);
200 		if (!error && *tp < stb.st_mtime) {
201 			*tp = stb.st_mtime;
202 			error = -1;
203 		} else {
204 			error = search_or_reload_file(mapf, map, key, pval, 0, 0);
205 		}
206 		(void) fclose(mapf);
207 		return error;
208 	}
209 
210 	return errno;
211 }
212 #endif /* HAS_FILE_MAPS */
213