xref: /netbsd-src/external/bsd/am-utils/dist/amd/info_file.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
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