138494Sobrien/* 2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 1938494Sobrien * 3. All advertising materials mentioning features or use of this software 2042629Sobrien * must display the following acknowledgment: 2138494Sobrien * This product includes software developed by the University of 2238494Sobrien * California, Berkeley and its contributors. 2338494Sobrien * 4. Neither the name of the University nor the names of its contributors 2438494Sobrien * may be used to endorse or promote products derived from this software 2538494Sobrien * without specific prior written permission. 2638494Sobrien * 2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3038494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3738494Sobrien * SUCH DAMAGE. 3838494Sobrien * 3938494Sobrien * 40174294Sobrien * File: am-utils/amd/info_file.c 4138494Sobrien * 4238494Sobrien */ 4338494Sobrien 4438494Sobrien/* 4538494Sobrien * Get info from file 4638494Sobrien */ 4738494Sobrien 4838494Sobrien#ifdef HAVE_CONFIG_H 4938494Sobrien# include <config.h> 5038494Sobrien#endif /* HAVE_CONFIG_H */ 5138494Sobrien#include <am_defs.h> 5238494Sobrien#include <amd.h> 5338494Sobrien 5438494Sobrien#define MAX_LINE_LEN 1500 5538494Sobrien 5638494Sobrien/* forward declarations */ 57174294Sobrienint file_init_or_mtime(mnt_map *m, char *map, time_t *tp); 5838494Sobrienint file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); 5938494Sobrienint file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); 6038494Sobrien 6138494Sobrien 6238494Sobrienstatic int 6382794Sobrienread_line(char *buf, int size, FILE *fp) 6438494Sobrien{ 6538494Sobrien int done = 0; 6638494Sobrien 6738494Sobrien do { 6838494Sobrien while (fgets(buf, size, fp)) { 6938494Sobrien int len = strlen(buf); 7038494Sobrien done += len; 7138494Sobrien if (len > 1 && buf[len - 2] == '\\' && 7238494Sobrien buf[len - 1] == '\n') { 7338494Sobrien int ch; 7438494Sobrien buf += len - 2; 7538494Sobrien size -= len - 2; 7638494Sobrien *buf = '\n'; 7738494Sobrien buf[1] = '\0'; 7838494Sobrien /* 7938494Sobrien * Skip leading white space on next line 8038494Sobrien */ 8138494Sobrien while ((ch = getc(fp)) != EOF && 8238494Sobrien isascii(ch) && isspace(ch)) ; 8338494Sobrien (void) ungetc(ch, fp); 8438494Sobrien } else { 8538494Sobrien return done; 8638494Sobrien } 8738494Sobrien } 88174294Sobrien } while (size > 0 && !feof(fp) && !ferror(fp)); 8938494Sobrien 9038494Sobrien return done; 9138494Sobrien} 9238494Sobrien 9338494Sobrien 9438494Sobrien/* 9538494Sobrien * Try to locate a key in a file 9638494Sobrien */ 9738494Sobrienstatic int 98174294Sobrienfile_search_or_reload(FILE *fp, 99174294Sobrien char *map, 100174294Sobrien char *key, 101174294Sobrien char **val, 102174294Sobrien mnt_map *m, 103174294Sobrien void (*fn) (mnt_map *m, char *, char *)) 10438494Sobrien{ 10538494Sobrien char key_val[MAX_LINE_LEN]; 10638494Sobrien int chuck = 0; 10738494Sobrien int line_no = 0; 10838494Sobrien 10938494Sobrien while (read_line(key_val, sizeof(key_val), fp)) { 11038494Sobrien char *kp; 11138494Sobrien char *cp; 11238494Sobrien char *hash; 11338494Sobrien int len = strlen(key_val); 11438494Sobrien line_no++; 11538494Sobrien 11638494Sobrien /* 11738494Sobrien * Make sure we got the whole line 11838494Sobrien */ 11938494Sobrien if (key_val[len - 1] != '\n') { 12038494Sobrien plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map); 12138494Sobrien chuck = 1; 12238494Sobrien } else { 12338494Sobrien key_val[len - 1] = '\0'; 12438494Sobrien } 12538494Sobrien 12638494Sobrien /* 12738494Sobrien * Strip comments 12838494Sobrien */ 12938494Sobrien hash = strchr(key_val, '#'); 13038494Sobrien if (hash) 13138494Sobrien *hash = '\0'; 13238494Sobrien 13338494Sobrien /* 13438494Sobrien * Find start of key 13538494Sobrien */ 13638494Sobrien for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ; 13738494Sobrien 13838494Sobrien /* 13938494Sobrien * Ignore blank lines 14038494Sobrien */ 14138494Sobrien if (!*kp) 14238494Sobrien goto again; 14338494Sobrien 14438494Sobrien /* 14538494Sobrien * Find end of key 14638494Sobrien */ 14738494Sobrien for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ; 14838494Sobrien 14938494Sobrien /* 15038494Sobrien * Check whether key matches 15138494Sobrien */ 15238494Sobrien if (*cp) 15338494Sobrien *cp++ = '\0'; 15438494Sobrien 15538494Sobrien if (fn || (*key == *kp && STREQ(key, kp))) { 15638494Sobrien while (*cp && isascii(*cp) && isspace((int)*cp)) 15738494Sobrien cp++; 15838494Sobrien if (*cp) { 15938494Sobrien /* 16038494Sobrien * Return a copy of the data 16138494Sobrien */ 16238494Sobrien char *dc = strdup(cp); 16338494Sobrien if (fn) { 16438494Sobrien (*fn) (m, strdup(kp), dc); 16538494Sobrien } else { 16638494Sobrien *val = dc; 16738494Sobrien dlog("%s returns %s", key, dc); 16838494Sobrien } 16938494Sobrien if (!fn) 17038494Sobrien return 0; 17138494Sobrien } else { 17238494Sobrien plog(XLOG_USER, "%s: line %d has no value field", map, line_no); 17338494Sobrien } 17438494Sobrien } 17538494Sobrien 17638494Sobrien again: 17738494Sobrien /* 17838494Sobrien * If the last read didn't get a whole line then 17938494Sobrien * throw away the remainder before continuing... 18038494Sobrien */ 18138494Sobrien if (chuck) { 18238494Sobrien while (fgets(key_val, sizeof(key_val), fp) && 18338494Sobrien !strchr(key_val, '\n')) ; 18438494Sobrien chuck = 0; 18538494Sobrien } 18638494Sobrien } 18738494Sobrien 18838494Sobrien return fn ? 0 : ENOENT; 18938494Sobrien} 19038494Sobrien 19138494Sobrien 19238494Sobrienstatic FILE * 19338494Sobrienfile_open(char *map, time_t *tp) 19438494Sobrien{ 19538494Sobrien FILE *mapf = fopen(map, "r"); 19638494Sobrien 19738494Sobrien if (mapf && tp) { 19838494Sobrien struct stat stb; 19938494Sobrien if (fstat(fileno(mapf), &stb) < 0) 200174294Sobrien *tp = clocktime(NULL); 20138494Sobrien else 20238494Sobrien *tp = stb.st_mtime; 20338494Sobrien } 20438494Sobrien return mapf; 20538494Sobrien} 20638494Sobrien 20738494Sobrien 20838494Sobrienint 209174294Sobrienfile_init_or_mtime(mnt_map *m, char *map, time_t *tp) 21038494Sobrien{ 21138494Sobrien FILE *mapf = file_open(map, tp); 21238494Sobrien 21338494Sobrien if (mapf) { 21438494Sobrien fclose(mapf); 21538494Sobrien return 0; 21638494Sobrien } 21738494Sobrien return errno; 21838494Sobrien} 21938494Sobrien 22038494Sobrien 22138494Sobrienint 22238494Sobrienfile_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) 22338494Sobrien{ 22438494Sobrien FILE *mapf = file_open(map, (time_t *) 0); 22538494Sobrien 22638494Sobrien if (mapf) { 227174294Sobrien int error = file_search_or_reload(mapf, map, 0, 0, m, fn); 22838494Sobrien (void) fclose(mapf); 22938494Sobrien return error; 23038494Sobrien } 23138494Sobrien return errno; 23238494Sobrien} 23338494Sobrien 23438494Sobrien 23538494Sobrienint 23638494Sobrienfile_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) 23738494Sobrien{ 23838494Sobrien time_t t; 23938494Sobrien FILE *mapf = file_open(map, &t); 24038494Sobrien 24138494Sobrien if (mapf) { 24238494Sobrien int error; 24338494Sobrien if (*tp < t) { 24438494Sobrien *tp = t; 24538494Sobrien error = -1; 24638494Sobrien } else { 247174294Sobrien error = file_search_or_reload(mapf, map, key, pval, 0, 0); 24838494Sobrien } 24938494Sobrien (void) fclose(mapf); 25038494Sobrien return error; 25138494Sobrien } 25238494Sobrien return errno; 25338494Sobrien} 254