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