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