[procps] [PATCH 2/2] sysctl: implement --pattern option

  • From: Ludwig Nussel <ludwig.nussel@xxxxxxx>
  • To: procps@xxxxxxxxxxxxx
  • Date: Tue, 24 May 2011 11:52:01 +0200

Useful for e.g network hook scripts together with --system to only apply
sysctls for a specific network interface.
---
 sysctl.8 |   14 ++++++++++++++
 sysctl.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/sysctl.8 b/sysctl.8
index 3bb46d7..b31ed0e 100644
--- a/sysctl.8
+++ b/sysctl.8
@@ -92,6 +92,16 @@ 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, /etc/sysctl.conf)
+.TP
+.B "--pattern" PATTERN
+Ignore settings that don't patch PATTERN. A star '*' is recognized
+as wildcard. It matches strings until the next dot. '**' at the end
+of the pattern matches until the end of the string.
 .SH EXAMPLES
 /sbin/sysctl \-a
 .br
@@ -100,6 +110,10 @@ Display all values currently available in table form.
 /sbin/sysctl \-w kernel.domainname="example.com"
 .br
 /sbin/sysctl \-p /etc/sysctl.conf
+.TP
+/sbin/sysctl --pattern 'net.ipv4.conf.*.forwarding' -a
+.TP
+/sbin/sysctl --pattern 'net.ipv6.**' --system
 .SH FILES
 .I /proc/sys
 .br
diff --git a/sysctl.c b/sysctl.c
index 3445efe..42fb568 100644
--- a/sysctl.c
+++ b/sysctl.c
@@ -50,6 +50,7 @@ static bool PrintName;
 static bool PrintNewline;
 static bool IgnoreError;
 static bool Quiet;
+static char* pattern;
 
 /* error messages */
 static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter 
\"%s\"\n";
@@ -63,6 +64,7 @@ static const char ERR_OPENING_DIR[] = "error: unable to open 
directory \"%s\"\n"
 static const char ERR_PRELOAD_FILE[] = "error: unable to open preload file 
\"%s\"\n";
 static const char WARN_BAD_LINE[] = "warning: %s(%d): invalid syntax, 
continuing...\n";
 
+static int pattern_match(const char* name);
 
 static void slashdot(char *restrict p, char old, char new){
   p = strpbrk(p,"/.");
@@ -135,16 +137,21 @@ static int ReadSetting(const char *restrict const name) {
       return -1;
    }
 
+   /* used to display the output */
+   outname = strdup(name);
+   slashdot(outname,'/','.'); /* change / to . */
+
+   if (pattern && !pattern_match(outname)){
+      free(outname);
+      return 0;
+   }
+
    /* used to open the file */
    tmpname = malloc(strlen(name)+strlen(PROC_PATH)+2);
    strcpy(tmpname, PROC_PATH);
    strcat(tmpname, name); 
    slashdot(tmpname+strlen(PROC_PATH),'.','/'); /* change . to / */
 
-   /* used to display the output */
-   outname = strdup(name);
-   slashdot(outname,'/','.'); /* change / to . */
-
    if (stat(tmpname, &ts) < 0) {
       if (!IgnoreError) {
          perror(tmpname);
@@ -391,7 +398,39 @@ out:
    return rc;
 }
 
+static int pattern_match(const char* name) {
+    const char* p = pattern;
+    if (!p || !name)
+        return 0;
+
+    while (*p && *name) {
+        if (*p == '*') {
+           ++p;
+           // collapse stars. if at end match rest of string
+           while (*p == '*') {
+               ++p;
+               if (!*p)
+                   return 1;
+           }
+            while (*name) {
+                if (*name == '.') {
+                    break;
+                }
+                ++name;
+            }
+            continue;
+        }
+        if (*p != *name)
+            return 0;
 
+        ++p;
+        ++name;
+        continue;
+    }
+    if (!*p && !*name)
+       return 1;
+    return 0;
+}
 
 /*
  *     Preload the sysctl's from the conf file
@@ -435,6 +474,10 @@ static int Preload(const char *restrict const filename) {
 
       StripLeadingAndTrailingSpaces(name);
 
+      if (pattern && !pattern_match(name)){
+          continue;
+      }
+
       value = strtok(NULL, "\n\r");
       if (!value || !*value) {
          fprintf(stderr, WARN_BAD_LINE, filename, n);
@@ -523,6 +566,16 @@ int main(int argc, char *argv[]) {
                  IgnoreError = true;
                  return PreloadSystem();
               }
+              if (!strcmp("--pattern",*argv)) {
+                  ++argv;
+                  if (*argv && **argv) {
+                      pattern = strdup(*argv);
+                      continue;
+                  } else {
+                      fprintf(stderr, "error: --pattern requires an 
argument\n");
+                      return 1;
+                  }
+              }
               fprintf(stderr, ERR_UNKNOWN_PARAMETER, *argv);
               return Usage(me);
          }
-- 
1.7.3.4


Other related posts:

  • » [procps] [PATCH 2/2] sysctl: implement --pattern option - Ludwig Nussel