138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 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. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174294Sobrien * File: am-utils/amd/info_file.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien/* 4138494Sobrien * Get info from file 4238494Sobrien */ 4338494Sobrien 4438494Sobrien#ifdef HAVE_CONFIG_H 4538494Sobrien# include <config.h> 4638494Sobrien#endif /* HAVE_CONFIG_H */ 4738494Sobrien#include <am_defs.h> 4838494Sobrien#include <amd.h> 49310490Scy#include <sun_map.h> 5038494Sobrien 5138494Sobrien 5238494Sobrien/* forward declarations */ 53174294Sobrienint file_init_or_mtime(mnt_map *m, char *map, time_t *tp); 5438494Sobrienint file_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)); 5538494Sobrienint file_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp); 5638494Sobrien 5738494Sobrien 58310490Scyint 59310490Scyfile_read_line(char *buf, int size, FILE *fp) 6038494Sobrien{ 6138494Sobrien int done = 0; 6238494Sobrien 6338494Sobrien do { 6438494Sobrien while (fgets(buf, size, fp)) { 6538494Sobrien int len = strlen(buf); 6638494Sobrien done += len; 6738494Sobrien if (len > 1 && buf[len - 2] == '\\' && 6838494Sobrien buf[len - 1] == '\n') { 6938494Sobrien int ch; 7038494Sobrien buf += len - 2; 7138494Sobrien size -= len - 2; 7238494Sobrien *buf = '\n'; 7338494Sobrien buf[1] = '\0'; 7438494Sobrien /* 7538494Sobrien * Skip leading white space on next line 7638494Sobrien */ 7738494Sobrien while ((ch = getc(fp)) != EOF && 78310490Scy isascii((unsigned char)ch) && isspace((unsigned char)ch)) ; 7938494Sobrien (void) ungetc(ch, fp); 8038494Sobrien } else { 8138494Sobrien return done; 8238494Sobrien } 8338494Sobrien } 84174294Sobrien } while (size > 0 && !feof(fp) && !ferror(fp)); 8538494Sobrien 8638494Sobrien return done; 8738494Sobrien} 8838494Sobrien 8938494Sobrien 9038494Sobrien/* 9138494Sobrien * Try to locate a key in a file 9238494Sobrien */ 9338494Sobrienstatic int 94310490Scyfile_search_or_reload(mnt_map *m, 95310490Scy FILE *fp, 96174294Sobrien char *map, 97174294Sobrien char *key, 98174294Sobrien char **val, 99174294Sobrien void (*fn) (mnt_map *m, char *, char *)) 10038494Sobrien{ 101310490Scy char key_val[INFO_MAX_LINE_LEN]; 10238494Sobrien int chuck = 0; 10338494Sobrien int line_no = 0; 10438494Sobrien 105310490Scy while (file_read_line(key_val, sizeof(key_val), fp)) { 10638494Sobrien char *kp; 10738494Sobrien char *cp; 10838494Sobrien char *hash; 10938494Sobrien int len = strlen(key_val); 11038494Sobrien line_no++; 11138494Sobrien 11238494Sobrien /* 11338494Sobrien * Make sure we got the whole line 11438494Sobrien */ 11538494Sobrien if (key_val[len - 1] != '\n') { 11638494Sobrien plog(XLOG_WARNING, "line %d in \"%s\" is too long", line_no, map); 11738494Sobrien chuck = 1; 11838494Sobrien } else { 11938494Sobrien key_val[len - 1] = '\0'; 12038494Sobrien } 12138494Sobrien 12238494Sobrien /* 12338494Sobrien * Strip comments 12438494Sobrien */ 12538494Sobrien hash = strchr(key_val, '#'); 12638494Sobrien if (hash) 12738494Sobrien *hash = '\0'; 12838494Sobrien 12938494Sobrien /* 13038494Sobrien * Find start of key 13138494Sobrien */ 132310490Scy for (kp = key_val; *kp && isascii((unsigned char)*kp) && isspace((unsigned char)*kp); kp++) ; 13338494Sobrien 13438494Sobrien /* 13538494Sobrien * Ignore blank lines 13638494Sobrien */ 13738494Sobrien if (!*kp) 13838494Sobrien goto again; 13938494Sobrien 14038494Sobrien /* 14138494Sobrien * Find end of key 14238494Sobrien */ 143310490Scy for (cp = kp; *cp && (!isascii((unsigned char)*cp) || !isspace((unsigned char)*cp)); cp++) ; 14438494Sobrien 14538494Sobrien /* 14638494Sobrien * Check whether key matches 14738494Sobrien */ 14838494Sobrien if (*cp) 14938494Sobrien *cp++ = '\0'; 15038494Sobrien 15138494Sobrien if (fn || (*key == *kp && STREQ(key, kp))) { 152310490Scy while (*cp && isascii((unsigned char)*cp) && isspace((unsigned char)*cp)) 15338494Sobrien cp++; 15438494Sobrien if (*cp) { 15538494Sobrien /* 15638494Sobrien * Return a copy of the data 15738494Sobrien */ 158310490Scy char *dc; 159310490Scy /* if m->cfm == NULL, not using amd.conf file */ 160310490Scy if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) 161310490Scy dc = sun_entry2amd(kp, cp); 162310490Scy else 163310490Scy dc = xstrdup(cp); 16438494Sobrien if (fn) { 165310490Scy (*fn) (m, xstrdup(kp), dc); 16638494Sobrien } else { 16738494Sobrien *val = dc; 16838494Sobrien dlog("%s returns %s", key, dc); 16938494Sobrien } 17038494Sobrien if (!fn) 17138494Sobrien return 0; 17238494Sobrien } else { 17338494Sobrien plog(XLOG_USER, "%s: line %d has no value field", map, line_no); 17438494Sobrien } 17538494Sobrien } 17638494Sobrien 17738494Sobrien again: 17838494Sobrien /* 17938494Sobrien * If the last read didn't get a whole line then 18038494Sobrien * throw away the remainder before continuing... 18138494Sobrien */ 18238494Sobrien if (chuck) { 18338494Sobrien while (fgets(key_val, sizeof(key_val), fp) && 18438494Sobrien !strchr(key_val, '\n')) ; 18538494Sobrien chuck = 0; 18638494Sobrien } 18738494Sobrien } 18838494Sobrien 18938494Sobrien return fn ? 0 : ENOENT; 19038494Sobrien} 19138494Sobrien 19238494Sobrien 19338494Sobrienstatic FILE * 19438494Sobrienfile_open(char *map, time_t *tp) 19538494Sobrien{ 19638494Sobrien FILE *mapf = fopen(map, "r"); 19738494Sobrien 19838494Sobrien if (mapf && tp) { 19938494Sobrien struct stat stb; 20038494Sobrien if (fstat(fileno(mapf), &stb) < 0) 201174294Sobrien *tp = clocktime(NULL); 20238494Sobrien else 20338494Sobrien *tp = stb.st_mtime; 20438494Sobrien } 20538494Sobrien return mapf; 20638494Sobrien} 20738494Sobrien 20838494Sobrien 20938494Sobrienint 210174294Sobrienfile_init_or_mtime(mnt_map *m, char *map, time_t *tp) 21138494Sobrien{ 21238494Sobrien FILE *mapf = file_open(map, tp); 21338494Sobrien 21438494Sobrien if (mapf) { 21538494Sobrien fclose(mapf); 21638494Sobrien return 0; 21738494Sobrien } 21838494Sobrien return errno; 21938494Sobrien} 22038494Sobrien 22138494Sobrien 22238494Sobrienint 22338494Sobrienfile_reload(mnt_map *m, char *map, void (*fn) (mnt_map *, char *, char *)) 22438494Sobrien{ 225310490Scy FILE *mapf = file_open(map, (time_t *) NULL); 22638494Sobrien 22738494Sobrien if (mapf) { 228310490Scy int error = file_search_or_reload(m, mapf, map, NULL, NULL, fn); 22938494Sobrien (void) fclose(mapf); 23038494Sobrien return error; 23138494Sobrien } 23238494Sobrien return errno; 23338494Sobrien} 23438494Sobrien 23538494Sobrien 23638494Sobrienint 23738494Sobrienfile_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) 23838494Sobrien{ 23938494Sobrien time_t t; 24038494Sobrien FILE *mapf = file_open(map, &t); 24138494Sobrien 24238494Sobrien if (mapf) { 24338494Sobrien int error; 24438494Sobrien if (*tp < t) { 24538494Sobrien *tp = t; 24638494Sobrien error = -1; 24738494Sobrien } else { 248310490Scy error = file_search_or_reload(m, mapf, map, key, pval, NULL); 24938494Sobrien } 25038494Sobrien (void) fclose(mapf); 25138494Sobrien return error; 25238494Sobrien } 25338494Sobrien return errno; 25438494Sobrien} 255