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