sysctl: implement --pattern option
authorLudwig Nussel <ludwig.nussel@suse.de>
Fri, 7 Oct 2011 07:10:50 +0000 (09:10 +0200)
committerSami Kerola <kerolasa@iki.fi>
Tue, 20 Dec 2011 16:17:03 +0000 (17:17 +0100)
Useful for e.g network hook scripts together with --system to only apply
sysctls for a specific network interface.

Signed-off-by: Ludwig Nussel <ludwig.nussel@suse.de>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
sysctl.8
sysctl.c

index bc3a8db75e728c3e45206d7ff6f16cc5c1f1c51d..9e4b9b759ad8aadc33d9fcc51737c997928b5a3a 100644 (file)
--- a/sysctl.8
+++ b/sysctl.8
@@ -80,6 +80,13 @@ Load settings from all system configuration files.
 .br
 /etc/sysctl.conf
 .TP
+\fB\-\-pattern\fR \fIpattern\fR
+Only apply settings that match
+.IR pattern .
+The
+.I pattern
+uses extended regular expression syntax.
+.TP
 \fB\-A\fR
 Alias of \fB\-a\fR
 .TP
@@ -111,12 +118,21 @@ Display version information and exit.
 /sbin/sysctl \-w kernel.domainname="example.com"
 .br
 /sbin/sysctl \-p /etc/sysctl.conf
+.br
+/sbin/sysctl \-a \-\-pattern forward
+.br
+/sbin/sysctl \-a \-\-pattern forward$
+.br
+/sbin/sysctl \-a \-\-pattern 'net.ipv4.conf.(eth|wlan)0.arp'
+.br
+/sbin/sysctl \-\-system \-\-pattern '^net.ipv6'
 .SH FILES
 .I /proc/sys
 .br
 .I /etc/sysctl.conf
 .SH SEE ALSO
 .BR sysctl.conf (5)
+.BR regex (7)
 .SH AUTHOR
 .UR staikos\@0wned.org
 George Staikos
index 37c256a9e6b2e23003928d5f26fbbff15cb24426..311d4b9ad58610eeee0c8349866115d560cc66e0 100644 (file)
--- a/sysctl.c
+++ b/sysctl.c
@@ -27,6 +27,7 @@
 #include <getopt.h>
 #include <libgen.h>
 #include <limits.h>
+#include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -53,6 +54,7 @@ static bool PrintName;
 static bool PrintNewline;
 static bool IgnoreError;
 static bool Quiet;
+static char *pattern;
 
 /* error messages */
 static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting \"%s\"\n";
@@ -65,6 +67,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 *string, const char *pattern);
 
 static void slashdot(char *restrict p, char old, char new){
   p = strpbrk(p,"/.");
@@ -99,8 +102,10 @@ static void __attribute__ ((__noreturn__))
           "  -N, --names          print variable names without values\n"
           "  -n, --values         print only values of a variables\n"
           "  -p, --load[=<file>]  read values from file\n"
-          "      --system         read values from all system directories\n"
           "  -f                   alias of -p\n"
+          "      --system         read values from all system directories\n"
+          "  -r, --pattern <expression>\n"
+          "                       select setting that match expression\n"
           "  -q, --quiet          do not echo variable set\n"
           "  -w, --write          enable writing a value to variable\n"
           "  -o                   does nothing\n"
@@ -156,6 +161,15 @@ 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, pattern)){
+      free(outname);
+      return 0;
+   }
+
    /* used to open the file */
    tmpname = malloc(strlen(name)+strlen(PROC_PATH)+2);
    strcpy(tmpname, PROC_PATH);
@@ -412,7 +426,21 @@ out:
    return rc;
 }
 
-
+static int pattern_match(const char *string, const char *pattern)
+{
+       int status;
+       regex_t re;
+
+       if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
+               return (0);     /* Report error. */
+       }
+       status = regexec(&re, string, (size_t) 0, NULL, 0);
+       regfree(&re);
+       if (status != 0) {
+               return (0);     /* Report error. */
+       }
+       return (1);
+}
 
 /*
  *     Preload the sysctl's from the conf file
@@ -456,6 +484,10 @@ static int Preload(const char *restrict const filename) {
 
       StripLeadingAndTrailingSpaces(name);
 
+      if (pattern && !pattern_match(name, pattern)){
+         continue;
+      }
+
       value = strtok(NULL, "\n\r");
       if (!value || !*value) {
          fprintf(stderr, WARN_BAD_LINE, filename, n);
@@ -573,6 +605,7 @@ int main(int argc, char *argv[])
        {"quiet", no_argument, NULL, 'q'},
        {"write", no_argument, NULL, 'w'},
        {"system", no_argument, NULL, SYSTEM_OPTION},
+       {"pattern", required_argument, NULL, 'r'},
        {"help", no_argument, NULL, 'h'},
        {"version", no_argument, NULL, 'V'},
        {NULL, 0, NULL, 0}
@@ -588,7 +621,7 @@ int main(int argc, char *argv[])
    }
 
    while ((c =
-           getopt_long(argc, argv, "bneNwfpqoxaAXVdh", longopts,
+           getopt_long(argc, argv, "bneNwfp::qoxaAXr:Vdh", longopts,
                        NULL)) != -1)
       switch (c) {
       case 'b':
@@ -633,6 +666,9 @@ int main(int argc, char *argv[])
       case SYSTEM_OPTION:
            IgnoreError = true;
            return PreloadSystem();
+      case 'r':
+           pattern = strdup(optarg);
+           break;
       case 'V':
            fprintf(stdout, "sysctl (%s)\n",procps_version);
            exit(0);