From 596511f915e210d27c84eaca0a5b4c7c48ec96e0 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Fri, 26 Aug 2011 11:31:39 +0200 Subject: [PATCH 2/3] implement --pattern option Useful for e.g network hook scripts together with --system to only apply sysctls for a specific network interface. --- sysctl.8 | 10 ++++++++- sysctl.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/sysctl.8 b/sysctl.8 index d2b0ceb..406bb59 100644 --- a/sysctl.8 +++ b/sysctl.8 @@ -69,6 +69,11 @@ Display all values currently available in table form. 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) +.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 .TP /sbin/sysctl -a @@ -77,7 +82,10 @@ Load settings from system configuration files (/lib/sysctl.d/*.conf, .TP /sbin/sysctl -w kernel.domainname="example.com" .TP -/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 .I /etc/sysctl.conf diff --git a/sysctl.c b/sysctl.c index bf4e529..1867777 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); @@ -562,6 +605,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