"Fossies" - the Fresh Open Source Software Archive

Member "passwdqc-2.0.3/passwdqc_load.c" (23 Jun 2023, 2754 Bytes) of package /linux/privat/passwdqc-2.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "passwdqc_load.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.4.0_vs_2.0.0.

    1 /*
    2  * Copyright (c) 2008,2009 by Dmitry V. Levin
    3  * Copyright (c) 2021 by Solar Designer
    4  * See LICENSE
    5  */
    6 
    7 #ifdef _MSC_VER
    8 #define _CRT_NONSTDC_NO_WARNINGS /* we use POSIX function names */
    9 #define _CRT_SECURE_NO_WARNINGS /* we use fopen(), strerror(), sprintf() */
   10 #endif
   11 
   12 #include <stdio.h>
   13 #include <stdlib.h>
   14 #include <string.h>
   15 #include <stdarg.h>
   16 #include <errno.h>
   17 #include <sys/stat.h>
   18 
   19 #include "passwdqc.h"
   20 #include "concat.h"
   21 
   22 static char *mkreason(const char *what, const char *pathname,
   23     unsigned int lineno, const char *why)
   24 {
   25     char buf[sizeof(unsigned int) * 3 + 1];
   26     const char *at_line = (lineno ? " at line " : "");
   27     const char *at_num = (lineno ? buf : "");
   28 
   29     if (lineno)
   30         sprintf(buf, "%u", lineno);
   31     return concat(what, " \"", pathname, "\"", at_line, at_num, ": ",
   32         (why ? why : strerror(errno)), NULL);
   33 }
   34 
   35 static int
   36 parse_file(FILE *fp, passwdqc_params_t *params, char **reason,
   37     const char *pathname)
   38 {
   39     unsigned int lineno;
   40     char buf[8192];
   41 
   42     for (lineno = 1; fgets(buf, sizeof(buf), fp); ++lineno) {
   43         char *str, *end, *rt;
   44         const char *cstr;
   45         int rc;
   46 
   47         if (strlen(buf) >= sizeof(buf) - 1) {
   48             *reason = mkreason("Error reading", pathname,
   49                 lineno, "Line too long");
   50             return -1;
   51         }
   52 
   53         str = buf + strspn(buf, " \t\r\n");
   54         if (!*str || *str == '#')
   55             continue;
   56 
   57         if ((end = strpbrk(str, "\r\n")))
   58             *end = '\0';
   59         else
   60             end = str + strlen(str);
   61 
   62         while (end > str && (*--end == ' ' || *end == '\t'))
   63             *end = '\0';
   64 
   65         cstr = str;
   66         if ((rc = passwdqc_params_parse(params, &rt, 1, &cstr))) {
   67             *reason = mkreason("Error loading", pathname,
   68                 lineno, (rt ? rt : "Out of memory"));
   69             free(rt);
   70             return rc;
   71         }
   72     }
   73 
   74     if (!feof(fp) || ferror(fp)) {
   75         *reason = mkreason("Error reading", pathname, 0, NULL);
   76         return -1;
   77     }
   78 
   79     return 0;
   80 }
   81 
   82 struct dev_ino_t;
   83 struct dev_ino_t {
   84     struct dev_ino_t *next;
   85     dev_t dev;
   86     ino_t ino;
   87 };
   88 
   89 static struct dev_ino_t *dev_ino_head;
   90 
   91 int
   92 passwdqc_params_load(passwdqc_params_t *params, char **reason,
   93     const char *pathname)
   94 {
   95     int rc;
   96     FILE *fp;
   97     struct dev_ino_t di, *di_p;
   98     struct stat st;
   99 
  100     if (!(fp = fopen(pathname, "r"))) {
  101         *reason = mkreason("Error opening", pathname, 0, NULL);
  102         return -1;
  103     }
  104 
  105     if (fstat(fileno(fp), &st)) {
  106         *reason = mkreason("Error stat", pathname, 0, NULL);
  107         fclose(fp);
  108         return -1;
  109     }
  110 
  111     di.dev = st.st_dev;
  112     di.ino = st.st_ino;
  113     for (di_p = dev_ino_head; di_p; di_p = di_p->next)
  114         if (di_p->dev == di.dev && di_p->ino == di.ino)
  115             break;
  116     if (di_p) {
  117         *reason = mkreason("Error opening", pathname, 0,
  118             "Loop detected");
  119         fclose(fp);
  120         return -1;
  121     }
  122 
  123     di.next = dev_ino_head;
  124     dev_ino_head = &di;
  125 
  126     rc = parse_file(fp, params, reason, pathname);
  127     fclose(fp);
  128 
  129     dev_ino_head = dev_ino_head->next;
  130     return rc;
  131 }