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