diff options
author | Tomas Mraz <tmraz@redhat.com> | 2015-07-17 17:08:43 +0200 |
---|---|---|
committer | Tomas Mraz <tmraz@redhat.com> | 2015-07-17 17:08:43 +0200 |
commit | fcf522db281ce23840f028a2ea44039f92c5e144 (patch) | |
tree | 61ae0be00aef732856b893478df3ed87cd9c9ba6 /src | |
parent | 2feba1307c3bcfc1592b4e4162ebf9967cc096c5 (diff) | |
download | libpwquality-fcf522db281ce23840f028a2ea44039f92c5e144.tar.gz |
Add implicit support for <cfgfile>.d/*.conf file parsing.
Diffstat (limited to 'src')
-rw-r--r-- | src/pwquality.h | 5 | ||||
-rw-r--r-- | src/settings.c | 69 |
2 files changed, 73 insertions, 1 deletions
diff --git a/src/pwquality.h b/src/pwquality.h index 2f09e82..32f5f02 100644 --- a/src/pwquality.h +++ b/src/pwquality.h @@ -77,7 +77,10 @@ pwquality_free_settings(pwquality_settings_t *pwq); /* Parse the configuration file (if cfgfile is NULL then the default one). * If auxerror is not NULL it also possibly returns auxiliary error information - * that must be passed into pwquality_strerror() function. */ + * that must be passed into pwquality_strerror() function. + * New in 1.3.0: First tries to parse all *.conf configuration files from + * <cfgfile>.d directory if it exists. Order of parsing determines what + values will be in effect - the latest wins. */ int pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror); diff --git a/src/settings.c b/src/settings.c index a6d6efa..a5f22be 100644 --- a/src/settings.c +++ b/src/settings.c @@ -12,6 +12,7 @@ #include <limits.h> #include <ctype.h> #include <errno.h> +#include <dirent.h> #include "pwquality.h" #include "pwqprivate.h" @@ -181,15 +182,83 @@ read_config_file(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror return rv; } +static int +filter_conf(const struct dirent *d) +{ + const char *p; + + if ((p = strstr(d->d_name, ".conf")) == NULL) + return 0; + + if (p[5] != '\0') + return 0; + + return 1; +} + +static int +comp_func(const struct dirent **a, const struct dirent **b) +{ + return strcmp ((*a)->d_name, (*b)->d_name); +} + /* parse the configuration file (if NULL then the default one) */ int pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror) { + char *dirname; + struct dirent **namelist; + int n; + int i; + int rv = 0; + if (auxerror) *auxerror = NULL; if (cfgfile == NULL) cfgfile = PWQUALITY_DEFAULT_CFGFILE; + /* read "*.conf" files from "<cfgfile>.d" directory first */ + + if (asprintf(&dirname, "%s.d", cfgfile) < 0) + return PWQ_ERROR_MEM_ALLOC; + + /* we do not care about scandir races here so we use scandir */ + n = scandir(dirname, &namelist, filter_conf, comp_func); + + if (n < 0) { + namelist = NULL; + + if (errno == ENOMEM) { + free(dirname); + return PWQ_ERROR_MEM_ALLOC; + } /* other errors are ignored */ + } + + for (i = 0; i < n; i++) { + char *subcfg; + + if (rv) { + free(namelist[i]); + continue; + } + + if (asprintf(&subcfg, "%s/%s", dirname, namelist[i]->d_name) < 0) + rv = PWQ_ERROR_MEM_ALLOC; + else { + rv = read_config_file(pwq, subcfg, auxerror); + if (rv == PWQ_ERROR_CFGFILE_OPEN) + rv = 0; /* ignore, this one does not modify auxerror */ + free(subcfg); + } + + free(namelist[i]); + } + free(dirname); + free(namelist); + + if (rv) + return rv; + return read_config_file(pwq, cfgfile, auxerror); } |