Add initial implementation of sysctl(8)

Needs a bit of cleanup (avoiding magic numbers etc.).
This commit is contained in:
sin 2014-04-17 15:18:38 +01:00
parent c354e5e1d3
commit 8b32decb6f
5 changed files with 151 additions and 2 deletions

View File

@ -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)

2
README
View File

@ -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

1
TODO
View File

@ -6,7 +6,6 @@ Tools
* swaplabel(8)
* last(1)
* losetup(8)
* sysctl
* lspci
* mkswap [-L]
* passwd

9
sysctl.8 Normal file
View File

@ -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.

139
sysctl.c Normal file
View File

@ -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;
}