You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.8 KiB
156 lines
3.8 KiB
/* sysctl.c - A utility to read and manipulate the sysctl parameters.
|
|
*
|
|
* Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com>
|
|
* Copyright 2014 Kyungwan Han <asura321@gmail.com>
|
|
*
|
|
* No Standard
|
|
|
|
USE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
|
|
|
|
config SYSCTL
|
|
bool "sysctl"
|
|
default y
|
|
help
|
|
usage: sysctl [-aAeNnqw] [-p [FILE] | KEY[=VALUE]...]
|
|
|
|
Read/write system control data (under /proc/sys).
|
|
|
|
-a,A Show all values
|
|
-e Don't warn about unknown keys
|
|
-N Don't print key values
|
|
-n Don't print key names
|
|
-p Read values from FILE (default /etc/sysctl.conf)
|
|
-q Don't show value after write
|
|
-w Only write values (object to reading)
|
|
*/
|
|
#define FOR_sysctl
|
|
#include "toys.h"
|
|
|
|
// Null terminate at =, return value
|
|
static char *split_key(char *key)
|
|
{
|
|
char *value = strchr(key, '=');
|
|
|
|
if (value) *(value++)=0;
|
|
|
|
return value;
|
|
}
|
|
|
|
static void replace_char(char *str, char old, char new)
|
|
{
|
|
for (; *str; str++) if (*str == old) *str = new;
|
|
}
|
|
|
|
static void key_error(char *key)
|
|
{
|
|
if (errno == ENOENT) {
|
|
if (!(toys.optflags & FLAG_e)) error_msg("unknown key '%s'", key);
|
|
} else perror_msg("key '%s'", key);
|
|
}
|
|
|
|
static int write_key(char *path, char *key, char *value)
|
|
{
|
|
int fd = open(path, O_WRONLY);
|
|
|
|
if (fd < 0) {
|
|
key_error(key);
|
|
|
|
return 0;
|
|
}
|
|
xwrite(fd, value, strlen(value));
|
|
xclose(fd);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Display all keys under a path
|
|
static int do_show_keys(struct dirtree *dt)
|
|
{
|
|
char *path, *data, *key;
|
|
|
|
if (!dirtree_notdotdot(dt)) return 0; // Skip . and ..
|
|
if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE;
|
|
|
|
path = dirtree_path(dt, 0);
|
|
data = readfile(path, 0, 0);
|
|
replace_char(key = path + 10, '/', '.'); // skip "/proc/sys/"
|
|
if (!data) key_error(key);
|
|
else {
|
|
// Print the parts that aren't switched off by flags.
|
|
if (!(toys.optflags & FLAG_n)) xprintf("%s", key);
|
|
if (!(toys.optflags & (FLAG_N|FLAG_n))) xprintf(" = ");
|
|
for (key = data+strlen(data); key > data && isspace(*--key); *key = 0);
|
|
if (!(toys.optflags & FLAG_N)) xprintf("%s", data);
|
|
if ((toys.optflags & (FLAG_N|FLAG_n)) != (FLAG_N|FLAG_n)) xputc('\n');
|
|
}
|
|
|
|
free(data);
|
|
free(path);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Read/write entries under a key. Accepts "key=value" in key if !value
|
|
static void process_key(char *key, char *value)
|
|
{
|
|
char *path;
|
|
|
|
if (!value) value = split_key(key);
|
|
if ((toys.optflags & FLAG_w) && !value) {
|
|
error_msg("'%s' not key=value", key);
|
|
|
|
return;
|
|
}
|
|
|
|
path = xmprintf("/proc/sys/%s", key);
|
|
replace_char(path, '.', '/');
|
|
// Note: failure to assign to a non-leaf node suppresses the display.
|
|
if (!(value && (!write_key(path, key, value) || (toys.optflags & FLAG_q)))) {
|
|
if (!access(path, R_OK)) dirtree_read(path, do_show_keys);
|
|
else key_error(key);
|
|
}
|
|
free(path);
|
|
}
|
|
|
|
void sysctl_main()
|
|
{
|
|
char **args = 0;
|
|
|
|
// Display all keys
|
|
if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys);
|
|
|
|
// read file
|
|
else if (toys.optflags & FLAG_p) {
|
|
FILE *fp = xfopen(*toys.optargs ? *toys.optargs : "/etc/sysctl.conf", "r");
|
|
size_t len;
|
|
|
|
for (;;) {
|
|
char *line = 0, *key, *val;
|
|
|
|
if (-1 == (len = getline(&line, &len, fp))) break;
|
|
key = line;
|
|
while (isspace(*key)) key++;
|
|
if (*key == '#' || *key == ';' || !*key) continue;
|
|
while (len && isspace(line[len-1])) line[--len] = 0;
|
|
if (!(val = split_key(line))) {
|
|
error_msg("'%s' not key=value", line);
|
|
continue;
|
|
}
|
|
|
|
// Trim whitespace around =
|
|
len = (val-line)-1;
|
|
while (len && isspace(line[len-1])) line[--len] = 0;
|
|
while (isspace(*val)) val++;;
|
|
|
|
process_key(key, val);
|
|
free(line);
|
|
}
|
|
fclose(fp);
|
|
|
|
// Loop through arguments, displaying or assigning as appropriate
|
|
} else {
|
|
if (!*toys.optargs) help_exit("Needs 1 arg");
|
|
for (args = toys.optargs; *args; args++) process_key(*args, 0);
|
|
}
|
|
}
|