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 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 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 * 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 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 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 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