[Toybox] New toy - sysctl
Georgi Chorbadzhiyski
gf at unixsol.org
Fri Mar 9 17:55:55 PST 2012
Attached is a new toy - sysctl. It depends on dirtree_for_each().
--
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
-------------- next part --------------
/* vi: set sw=4 ts=4:
*
* sysctl.c - configure kernel parameters at runtime
*
* Copyright 2012 Georgi Chorbadzhiyski <georgi at unixsol.org>
*
* Not in SUSv4.
USE_SYSCTL(NEWTOY(sysctl, "w:p:nNeqaA", TOYFLAG_SBIN))
config SYSCTL
bool "sysctl"
default y
help
usage: sysctl [-aqeNn] [-w variable=value] [-p <file>] [variable]
Configure kernel parameters at runtime
-a Show all available parameters and their values.
-q Do not show values that are being set.
-e Ignore errors about unknown keys.
-N Show only parameters.
-n Show only values.
-w Set variable=value.
-p Load variables from <file>. Set to - to read from stdin.
*/
#include "toys.h"
#define FLAG_n 32
#define FLAG_N 16
#define FLAG_e 8
#define FLAG_q 4
#define FLAG_a 2
#define FLAG_A 1
DEFINE_GLOBALS(
char *file;
char *var;
char path[1024];
char sysctl[1024];
)
#define TT this.sysctl
static char *proc = "/proc";
static char *proc_sys = "/proc/sys";
static int show_sysctl_value(char *path, char *sysctl) {
char val_buf[4096];
char *val = val_buf;
char *nl;
int len;
int f = open(path, O_RDONLY);
if (f < 0) {
perror_msg("%s", TT.sysctl);
return 0;
}
len = read(f, val_buf, sizeof(val_buf));
if (len <= 0) {
close(f);
return 0;
}
val_buf[len] = '\0';
while ((nl = strchr(val, '\n'))) {
nl[0] = '\0';
if (toys.optflags & FLAG_N) {
xprintf("%s\n", TT.sysctl);
} else if (toys.optflags & FLAG_n) {
xprintf("%s\n", val);
} else {
xprintf("%s = %s\n", TT.sysctl, val);
}
val = nl + 1; // Move to next line
}
close(f);
return 1;
}
static int prepare_vars(char *prefix, char *path) {
struct stat st;
int i, len;
snprintf(TT.path, sizeof(TT.path) - 1, "%s/%s", prefix, path);
TT.path[sizeof(TT.path) - 1] = '\0';
if (stat(TT.path, &st) != 0) {
if (toys.optflags & FLAG_e && errno != ENOENT)
perror_msg("%s", path);
else if ((toys.optflags & FLAG_e) == 0)
perror_msg("%s", path);
return 0;
}
if (!S_ISREG(st.st_mode))
return 0;
strcpy(TT.sysctl, TT.path + strlen(prefix) + 1);
len = strlen(TT.sysctl);
for (i = 0; i < len; i++) {
if (TT.sysctl[i] == '/')
TT.sysctl[i] = '.';
}
return 1;
}
static int write_sysctl_variable(char *variable) {
char *path = variable;
char *value = strchr(variable, '=');
if (!value) {
error_msg("invalid format: %s", variable);
return 255;
}
value[0] = '\0';
value++;
int i, len = strlen(path);
for (i = 0; i < len; i++) {
if (path[i] == '.')
path[i] = '/';
}
if (!prepare_vars(proc_sys, path))
return 255;
int f = open(TT.path, O_WRONLY);
if (f < 0) {
perror_msg("%s", TT.sysctl);
return 255;
}
write(f, value, strlen(value));
close(f);
if ((toys.optflags & FLAG_q) == 0) {
int len = strlen(value);
while (len && value[--len] == '\n')
value[len] = '\0';
xprintf("%s = %s\n", TT.sysctl, value);
}
return 0;
}
// Called by dirtree_for_each
static int show_sysctl(char *path) {
if (prepare_vars(proc, path))
show_sysctl_value(TT.path, TT.sysctl);
return 0;
}
void sysctl_main(void)
{
if (toys.optflags & FLAG_A || toys.optflags & FLAG_a) {
// Show all sysctl values
toys.optflags &= ~FLAG_n;
toys.optflags &= ~FLAG_N;
dirtree_for_each(proc_sys, show_sysctl);
} else if (TT.file) {
int f = 1; // stdin
char *line;
if (strcmp(TT.file, "-") != 0) {
f = xopen(TT.file, O_RDONLY);
}
while ((line = get_line(f))) {
toys.exitval |= write_sysctl_variable(line);
}
close(f);
} else if (TT.var) {
toys.exitval = write_sysctl_variable(TT.var);
} else {
// Show sysctl value(s)
char **arg;
for (arg = toys.optargs; *arg; arg++) {
char *var = *arg;
int i, len = strlen(var);
for (i = 0; i < len; i++) {
if (var[i] == '.')
var[i] = '/';
}
if (prepare_vars(proc_sys, var)) {
if (!show_sysctl_value(TT.path, TT.sysctl))
toys.exitval = 255;
} else {
if (toys.optflags & FLAG_e) {
if (errno != ENOENT)
toys.exitval = 255;
} else {
toys.exitval = 255;
}
}
}
}
}
More information about the Toybox
mailing list