commit 8b32decb6feabf771a06aed6f9c19fa27da7f1f6
parent c354e5e1d34eabdc31f4fefe89c4f3712a942368
Author: sin <sin@2f30.org>
Date: Thu, 17 Apr 2014 15:18:38 +0100
Add initial implementation of sysctl(8)
Needs a bit of cleanup (avoiding magic numbers etc.).
Diffstat:
5 files changed, 151 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
@@ -47,6 +47,7 @@ SRC = \
swapoff.c \
swapon.c \
switch_root.c \
+ sysctl.c \
truncate.c \
umount.c \
unshare.c \
@@ -92,6 +93,7 @@ MAN8 = \
swapoff.8 \
swapon.8 \
switch_root.8 \
+ sysctl.8 \
umount.8
OBJ = $(SRC:.c=.o) $(LIB)
diff --git a/README b/README
@@ -9,7 +9,7 @@ The following programs are currently implemented:
chvt clear ctrlaltdel df dmesg eject fallocate free getty halt id
insmod killall5 lsmod lsusb mknod mkswap mount mountpoint pagesize
pidof pivot_root ps respawn rmmod stat su swapoff swapon
- switch_root truncate umount unshare uptime watch who
+ switch_root sysctl truncate umount unshare uptime watch who
The complement of ubase is sbase[1] which mostly follows POSIX and
provides all the portable tools. Together they are intended to form a
diff --git a/TODO b/TODO
@@ -6,7 +6,6 @@ Tools
* swaplabel(8)
* last(1)
* losetup(8)
- * sysctl
* lspci
* mkswap [-L]
* passwd
diff --git a/sysctl.8 b/sysctl.8
@@ -0,0 +1,9 @@
+.TH SYSCTL 8 ubase-VERSION
+.SH NAME
+\fBsysctl\fR - Configure kernel parameters at runtime
+.SH SYNOPSIS
+\fBsysctl\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.
diff --git a/sysctl.c b/sysctl.c
@@ -0,0 +1,139 @@
+/* See LICENSE file for copyright and license details. */
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "util.h"
+
+static int
+getsysctl(char *variable, char **value)
+{
+ char path[PATH_MAX];
+ char *p;
+ char *buf;
+ int fd;
+ ssize_t n;
+
+ for (p = variable; *p; p++)
+ if (*p == '.')
+ *p = '/';
+
+ strlcpy(path, "/proc/sys/", sizeof(path));
+ if (strlcat(path, variable, sizeof(path)) >= sizeof(path))
+ return -1;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ buf = malloc(1024);
+ if (!buf) {
+ close(fd);
+ return -1;
+ }
+
+ n = read(fd, buf, 1023);
+ if (n <= 0) {
+ close(fd);
+ free(buf);
+ return -1;
+ }
+ buf[n] = '\0';
+
+ p = strrchr(buf, '\n');
+ if (p)
+ *p = '\0';
+
+ *value = buf;
+
+ close(fd);
+
+ return 0;
+}
+
+static int
+setsysctl(char *variable, char *value)
+{
+ char path[PATH_MAX];
+ char *p;
+ int fd;
+ ssize_t n;
+
+ for (p = variable; *p; p++)
+ if (*p == '.')
+ *p = '/';
+
+ strlcpy(path, "/proc/sys/", sizeof(path));
+ if (strlcat(path, variable, sizeof(path)) >= sizeof(path))
+ return -1;
+
+ fd = open(path, O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ n = write(fd, value, strlen(value));
+ if (n != (ssize_t)strlen(value)) {
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+static void
+usage(void)
+{
+ eprintf("usage: %s variable[=value]...\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *variable;
+ char *value;
+ char *p;
+ int i;
+
+ argv0 = argv[0];
+ argv++;
+ argc--;
+
+ if (argc < 1)
+ usage();
+
+ for (i = 0; i < argc; i++) {
+ value = NULL;
+ variable = argv[i];
+ p = strchr(variable, '=');
+ if (p) {
+ if (p[1] == '\0') {
+ weprintf("malformed sysctl: %s\n", argv[i]);
+ continue;
+ }
+ *p = '\0';
+ value = &p[1];
+ }
+ if (variable) {
+ if (value) {
+ if (setsysctl(variable, value) < 0) {
+ weprintf("failed to set sysctl for %s\n", variable);
+ continue;
+ }
+ }
+ else {
+ if (getsysctl(variable, &value) < 0) {
+ weprintf("failed to get sysctl for %s\n", variable);
+ continue;
+ }
+ printf("%s = %s\n", variable, value);
+ free(value);
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
+}