commit 191cc71cee5846e680ef12b3e1707f13bf4e0832
parent db0ea785f0231be4315aa4c5af37e64841ce48f2
Author: sin <sin@2f30.org>
Date: Fri, 13 Jun 2014 15:20:21 +0100
sysctl: Add support for loading key:value pairs from file
Diffstat:
M | sysctl.8 | | | 6 | +++++- |
M | sysctl.c | | | 119 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
2 files changed, 81 insertions(+), 44 deletions(-)
diff --git a/sysctl.8 b/sysctl.8
@@ -2,8 +2,12 @@
.SH NAME
\fBsysctl\fR - Configure kernel parameters at runtime
.SH SYNOPSIS
-\fBsysctl\fR \fIvariable\fR[=\fIvalue\fR]...
+\fBsysctl\fR [\fB-p\fR \fIfile\fR] \fIvariable\fR[=\fIvalue\fR]...
.SH DESCRIPTION
\fBsysctl\fR modifies kernel parameters at runtime. The parameters available
are those listed under \fI/proc/sys/\fR. Procfs is required for sysctl support
in Linux. You can use \fBsysctl\fR to both read and write sysctl data.
+.SH OPTIONS
+.TP
+\fB-p\fR
+Load the sysctl key:value pairs from \fIfile\fR.
diff --git a/sysctl.c b/sysctl.c
@@ -108,68 +108,101 @@ setsysctl(char *variable, char *value)
return 0;
}
+static int
+parsepair(char *pair)
+{
+ char *p;
+ char *variable;
+ char *value;
+
+ for (p = pair; *p; p++) {
+ if (p[0] == '.' && p[1] == '.') {
+ weprintf("malformed input: %s\n", pair);
+ return -1;
+ }
+ }
+ p = strchr(pair, '=');
+ if (p) {
+ if (p[1] == '\0') {
+ weprintf("malformed input: %s\n", pair);
+ return -1;
+ }
+ *p = '\0';
+ value = &p[1];
+ } else {
+ value = NULL;
+ }
+ variable = pair;
+ if (value) {
+ if (setsysctl(variable, value) < 0) {
+ weprintf("failed to set sysctl for %s\n", variable);
+ return -1;
+ }
+ } else {
+ if (getsysctl(variable, &value) < 0) {
+ weprintf("failed to get sysctl for %s\n", variable);
+ return -1;
+ }
+ printf("%s = %s\n", variable, value);
+ free(value);
+ }
+
+ return 0;
+}
+
static void
usage(void)
{
- eprintf("usage: %s variable[=value]...\n", argv0);
+ eprintf("usage: %s [-p file] variable[=value]...\n", argv0);
}
int
main(int argc, char *argv[])
{
- char *variable;
- char *value;
- char *p;
+ FILE *fp;
+ char buf[BUFSIZ], *p;
+ char *file = NULL;
int i;
int r = EXIT_SUCCESS;
- argv0 = argv[0];
- argv++;
- argc--;
-
- if (argc < 1)
+ ARGBEGIN {
+ case 'p':
+ file = EARGF(usage());
+ break;
+ default:
usage();
+ } ARGEND;
- for (i = 0; i < argc; i++) {
- for (p = argv[i]; *p; p++) {
- if (p[0] == '.' && p[1] == '.') {
- r = EXIT_FAILURE;
- weprintf("malformed input: %s\n", argv[i]);
- break;
- }
- }
- if (*p != '\0')
- continue;
- p = strchr(argv[i], '=');
- if (p) {
- if (p[1] == '\0') {
- r = EXIT_FAILURE;
- weprintf("malformed input: %s\n", argv[i]);
- continue;
- }
- *p = '\0';
- value = &p[1];
- } else {
- value = NULL;
- }
- variable = argv[i];
+ if (!file && argc < 1)
+ usage();
- if (value) {
- if (setsysctl(variable, value) < 0) {
+ if (!file) {
+ for (i = 0; i < argc; i++)
+ if (parsepair(argv[i]) < 0)
r = EXIT_FAILURE;
- weprintf("failed to set sysctl for %s\n", variable);
+ } else {
+ fp = fopen(file, "r");
+ if (!fp)
+ eprintf("fopen %s:", file);
+ while (fgets(buf, sizeof(buf), fp)) {
+ p = buf;
+ for (p = buf; *p == ' ' || *p == '\t'; p++)
+ ;
+ if (*p == '#' || *p == '\n')
continue;
+ for (p = buf; *p; p++) {
+ if (*p == '\n') {
+ *p = '\0';
+ break;
+ }
}
- }
- else {
- if (getsysctl(variable, &value) < 0) {
+ p = buf;
+ if (parsepair(p) < 0)
r = EXIT_FAILURE;
- weprintf("failed to get sysctl for %s\n", variable);
- continue;
- }
- printf("%s = %s\n", variable, value);
- free(value);
}
+ if (ferror(fp))
+ eprintf("%s: read error:", file);
+ fclose(fp);
}
return r;