From f09de20e534804464d89d76c607ac877573ad9fe Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Fri, 26 Aug 2011 11:11:50 +0200 Subject: [PATCH 1/3] add --system switch instead of requiring distributions to construct a loop around sysctl in boot scripts just scan a set of default directories if the --system switch is used. Config files are applied in alphabetic order of their base name. Each base name is only applied once according to the directory preference. /etc/sysctl.conf is always applied last. --- sysctl.8 | 5 ++++ sysctl.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 0 deletions(-) diff --git a/sysctl.8 b/sysctl.8 index e26c4fb..d2b0ceb 100644 --- a/sysctl.8 +++ b/sysctl.8 @@ -64,6 +64,11 @@ Display all values currently available. .TP .B "-A" Display all values currently available in table form. +.TP +.B "--system" +Load settings from system configuration files (/lib/sysctl.d/*.conf, +/usr/lib/sysctl.d/*.conf, /usr/local/lib/sysctl.d/*.conf, +/etc/sysctl.d/*.conf, /run/sysctl.d/*.conf, /etc/sysctl.conf) .SH EXAMPLES .TP /sbin/sysctl -a diff --git a/sysctl.c b/sysctl.c index 9be79ce..bf4e529 100644 --- a/sysctl.c +++ b/sysctl.c @@ -453,6 +453,76 @@ static int Preload(const char *restrict const filename) { return rc; } +struct pair { + char* name; + char* value; +}; + +static int sortpairs(const void* A, const void* B) +{ + const struct pair* a = *(struct pair* const*)A; + const struct pair* b = *(struct pair* const*)B; + return strcmp(a->name, b->name); +} + +static int PreloadSystem(void) { + unsigned di, i; + const char* dirs[] = { + "/run/sysctl.d", + "/etc/sysctl.d", + "/usr/local/lib/sysctl.d", + "/usr/lib/sysctl.d", + "/lib/sysctl.d", + }; + struct pair** cfgs = NULL; + unsigned ncfgs = 0; + enum { nprealloc = 16 }; + + for (di=0; di < sizeof(dirs)/sizeof(dirs[0]); ++di) { + struct dirent* de; + DIR* dp = opendir(dirs[di]); + if (!dp) + continue; + while (( de = readdir(dp) )) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + continue; + } + if (strlen(de->d_name) < 6 || !strcmp(de->d_name+strlen(de->d_name)-6, ".conf")) + continue; + /* check if config already known */ + for (i = 0; i < ncfgs; ++i) { + if (!strcmp(cfgs[i]->name, de->d_name)) + break; + } + if (i < ncfgs) // already in + continue; + + if (ncfgs % nprealloc == 0) { + cfgs = realloc(cfgs, sizeof(struct pair*)*(ncfgs+nprealloc)); + } + cfgs[ncfgs] = malloc(sizeof(struct pair) + strlen(de->d_name)*2+2 + strlen(dirs[di])+1); + cfgs[ncfgs]->name = (char*)cfgs[ncfgs]+sizeof(struct pair); + strcpy(cfgs[ncfgs]->name, de->d_name); + cfgs[ncfgs]->value = (char*)cfgs[ncfgs]+sizeof(struct pair) + strlen(cfgs[ncfgs]->name)+1; + sprintf(cfgs[ncfgs]->value, "%s/%s", dirs[di], de->d_name); + ncfgs++; + + } + closedir(dp); + } + + qsort(cfgs, ncfgs, sizeof(struct cfg*), sortpairs); + + for (i = 0; i < ncfgs; ++i) { + if (!Quiet) + printf("* Applying %s ...\n", cfgs[i]->value); + Preload(cfgs[i]->value); + } + + if (!Quiet) + printf("* Applying %s ...\n", DEFAULT_PRELOAD); + return Preload(DEFAULT_PRELOAD); +} /* @@ -488,6 +558,10 @@ int main(int argc, char *argv[]) { fprintf(stdout, "sysctl (%s)\n",procps_version); exit(0); } + if (!strcmp("--system",*argv)) { + IgnoreError = true; + return PreloadSystem(); + } fprintf(stderr, ERR_UNKNOWN_PARAMETER, *argv); return Usage(me); } -- 1.7.3.4