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