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