Logo Search packages:      
Sourcecode: passwdqc version File versions  Download package

passwdqc_load.c

/*
 * Copyright (c) 2008,2009 by Dmitry V. Levin.  See LICENSE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>

#include "passwdqc.h"
#include "concat.h"

static char *mkreason(const char *what, const char *pathname,
    unsigned int lineno, const char *why)
{
      char buf[sizeof(unsigned int) * 3 + 1];
      const char *at_line = (lineno ? " at line " : "");
      const char *at_num = (lineno ? buf : "");

      if (lineno)
            sprintf(buf, "%u", lineno);
      return concat(what, " \"", pathname, "\"", at_line, at_num, ": ",
          (why ? why : strerror(errno)), NULL);
}

static char *
skip_whitespaces(char *str)
{
      char *p;

      for (p = str; *p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'; ++p)
            ;
      return p;
}

static char *
skip_nonwhitespaces(char *str)
{
      char *p;

      for (p = str;
          *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n'; ++p)
            ;
      return p;
}

static int
parse_file(FILE *fp, passwdqc_params_t *params, char **reason,
    const char *pathname)
{
      unsigned int lineno;
      char buf[8192];

      for (lineno = 1; fgets(buf, sizeof(buf), fp); ++lineno) {
            char *str, *end, *rt;
            const char *cstr;
            int rc;

            if (strlen(buf) >= sizeof(buf) - 1) {
                  *reason = mkreason("Error reading", pathname,
                      lineno, "Line too long");
                  return -1;
            }

            str = skip_whitespaces(buf);
            if (!*str || *str == '#')
                  continue;

            end = skip_nonwhitespaces(str);
            if (*skip_whitespaces(end)) {
                  *reason = mkreason("Error loading", pathname,
                      lineno, "Unexpected token");
                  return -1;
            }
            *end = '\0';

            cstr = str;
            if ((rc = passwdqc_params_parse(params, &rt, 1, &cstr))) {
                  *reason = mkreason("Error loading", pathname,
                      lineno, (rt ? rt : "Out of memory"));
                  free(rt);
                  return rc;
            }
      }

      if (!feof(fp) || ferror(fp)) {
            *reason = mkreason("Error reading", pathname, 0, NULL);
            return -1;
      }

      return 0;
}

struct dev_ino_t;
struct dev_ino_t {
      struct dev_ino_t *next;
      dev_t dev;
      ino_t ino;
};

static struct dev_ino_t *dev_ino_head;

int
passwdqc_params_load(passwdqc_params_t *params, char **reason,
    const char *pathname)
{
      int rc;
      FILE *fp;
      struct dev_ino_t di, *di_p;
      struct stat st;

      if (!(fp = fopen(pathname, "r"))) {
            *reason = mkreason("Error opening", pathname, 0, NULL);
            return -1;
      }

      if (fstat(fileno(fp), &st)) {
            *reason = mkreason("Error stat", pathname, 0, NULL);
            fclose(fp);
            return -1;
      }

      di.dev = st.st_dev;
      di.ino = st.st_ino;
      for (di_p = dev_ino_head; di_p; di_p = di_p->next)
            if (di_p->dev == di.dev && di_p->ino == di.ino)
                  break;
      if (di_p) {
            *reason = mkreason("Error opening", pathname, 0,
                "Loop detected");
            fclose(fp);
            return -1;
      }

      di.next = dev_ino_head;
      dev_ino_head = &di;

      rc = parse_file(fp, params, reason, pathname);
      fclose(fp);

      dev_ino_head = dev_ino_head->next;
      return rc;
}

Generated by  Doxygen 1.6.0   Back to index