From 100959274c9d9fa66a570099d4d4a3d6c257fb1f Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Fri, 7 Oct 2011 09:10:49 +0200 Subject: [PATCH] sysctl: 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. Signed-off-by: Ludwig Nussel Signed-off-by: Sami Kerola --- sysctl.8 | 15 +++++++++++ sysctl.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/sysctl.8 b/sysctl.8 index 64ca3203..bc3a8db7 100644 --- a/sysctl.8 +++ b/sysctl.8 @@ -65,6 +65,21 @@ Display all values currently available. \fB\-b\fR, \fB\-\-binary\fR Print value without new line. .TP +\fB\-\-system\fR +Load settings from all system configuration files. +.br +/run/sysctl.d/*.conf +.br +/etc/sysctl.d/*.conf +.br +/usr/local/lib/sysctl.d/*.conf +.br +/usr/lib/sysctl.d/*.conf +.br +/lib/sysctl.d/*.conf +.br +/etc/sysctl.conf +.TP \fB\-A\fR Alias of \fB\-a\fR .TP diff --git a/sysctl.c b/sysctl.c index f912b624..37c256a9 100644 --- a/sysctl.c +++ b/sysctl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ static void __attribute__ ((__noreturn__)) " -N, --names print variable names without values\n" " -n, --values print only values of a variables\n" " -p, --load[=] read values from file\n" + " --system read values from all system directories\n" " -f alias of -p\n" " -q, --quiet do not echo variable set\n" " -w, --write enable writing a value to variable\n" @@ -472,6 +474,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 +560,9 @@ int main(int argc, char *argv[]) int c; const char *preloadfile = DEFAULT_PRELOAD; + enum { + SYSTEM_OPTION = CHAR_MAX + 1 + }; static const struct option longopts[] = { {"all", no_argument, NULL, 'a'}, {"binary", no_argument, NULL, 'b'}, @@ -497,6 +572,7 @@ int main(int argc, char *argv[]) {"load", optional_argument, NULL, 'p'}, {"quiet", no_argument, NULL, 'q'}, {"write", no_argument, NULL, 'w'}, + {"system", no_argument, NULL, SYSTEM_OPTION}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} @@ -554,6 +630,9 @@ int main(int argc, char *argv[]) case 'X': /* same as -a -x */ DisplayAllOpt = true; break; + case SYSTEM_OPTION: + IgnoreError = true; + return PreloadSystem(); case 'V': fprintf(stdout, "sysctl (%s)\n",procps_version); exit(0);