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