197c2c1eba507d10005e305098c3fc21b1472c97eRob Landley/* sysctl.c - A utility to read and manipulate the sysctl parameters.
297c2c1eba507d10005e305098c3fc21b1472c97eRob Landley *
397c2c1eba507d10005e305098c3fc21b1472c97eRob Landley * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com>
497c2c1eba507d10005e305098c3fc21b1472c97eRob Landley * Copyright 2014 Kyungwan Han <asura321@gmail.com>
597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley *
697c2c1eba507d10005e305098c3fc21b1472c97eRob Landley * No Standard
797c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
81dd3704c5ffea926f61a96bb7de7d9dbee52fa44Paul BarkerUSE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
997c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
1097c2c1eba507d10005e305098c3fc21b1472c97eRob Landleyconfig SYSCTL
1197c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  bool "sysctl"
1297641f459a3e74045305b4ef9b80bb00bc56a29fRob Landley  default y
1397c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  help
14e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    usage: sysctl [-aAeNnqw] [-p [FILE] | KEY[=VALUE]...]
1597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
16e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    Read/write system control data (under /proc/sys).
17f272df9e821e00afb962a62556318cecfcd694aeRob Landley
18e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -a,A	Show all values
19e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -e	Don't warn about unknown keys
20e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -N	Don't print key values
21e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -n	Don't print key names
228941e5fef58025591b7441372d486cf5de46dd39Rob Landley    -p	Read values from FILE (default /etc/sysctl.conf)
23e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -q	Don't show value after write
24e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    -w	Only write values (object to reading)
2597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley*/
2697c2c1eba507d10005e305098c3fc21b1472c97eRob Landley#define FOR_sysctl
2797c2c1eba507d10005e305098c3fc21b1472c97eRob Landley#include "toys.h"
2897c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
29e973d23094883ad66ec24247cb95dbe65db1324eRob Landley// Null terminate at =, return value
30e973d23094883ad66ec24247cb95dbe65db1324eRob Landleystatic char *split_key(char *key)
3197c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
32e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  char *value = strchr(key, '=');
33e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
34e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (value) *(value++)=0;
35e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
36e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  return value;
3797c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
3897c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
3997c2c1eba507d10005e305098c3fc21b1472c97eRob Landleystatic void replace_char(char *str, char old, char new)
4097c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
41f272df9e821e00afb962a62556318cecfcd694aeRob Landley  for (; *str; str++) if (*str == old) *str = new;
4297c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
4397c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
44e973d23094883ad66ec24247cb95dbe65db1324eRob Landleystatic void key_error(char *key)
4597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
4608f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  if (errno == ENOENT) {
4708f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley    if (!(toys.optflags & FLAG_e)) error_msg("unknown key '%s'", key);
4808f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  } else perror_msg("key '%s'", key);
4997c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
5097c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
51e973d23094883ad66ec24247cb95dbe65db1324eRob Landleystatic int write_key(char *path, char *key, char *value)
5297c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
53e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  int fd = open(path, O_WRONLY);;
5497c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
55e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (fd < 0) {
56e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    key_error(key);
57e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
58e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    return 0;
5997c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  }
60e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  xwrite(fd, value, strlen(value));
6197c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  xclose(fd);
6297c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
63e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  return 1;
6497c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
6597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
66e973d23094883ad66ec24247cb95dbe65db1324eRob Landley// Display all keys under a path
67e973d23094883ad66ec24247cb95dbe65db1324eRob Landleystatic int do_show_keys(struct dirtree *dt)
6897c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
69e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  char *path, *data, *key;
7097c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
71e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (!dirtree_notdotdot(dt)) return 0; // Skip . and ..
72e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE;
73e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
74e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  path = dirtree_path(dt, 0);
75e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  data = readfile(path, 0, 0);
76e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  replace_char(key = path + 10, '/', '.'); // skip "/proc/sys/"
77e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (!data) key_error(key);
78e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  else {
79e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    // Print the parts that aren't switched off by flags.
80e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    if (!(toys.optflags & FLAG_n)) xprintf("%s", key);
81e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    if (!(toys.optflags & (FLAG_N|FLAG_n))) xprintf(" = ");
82e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    for (key = data+strlen(data); key > data && isspace(*--key); *key = 0);
83e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    if (!(toys.optflags & FLAG_N)) xprintf("%s", data);
84e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    if ((toys.optflags & (FLAG_N|FLAG_n)) != (FLAG_N|FLAG_n)) xputc('\n');
8597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  }
8697c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
87e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  free(data);
88e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  free(path);
89e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
90e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  return 0;
91f272df9e821e00afb962a62556318cecfcd694aeRob Landley}
92f272df9e821e00afb962a62556318cecfcd694aeRob Landley
9308f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley// Read/write entries under a key. Accepts "key=value" in key if !value
94e973d23094883ad66ec24247cb95dbe65db1324eRob Landleystatic void process_key(char *key, char *value)
9597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
9608f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  char *path;
9797c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
9808f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  if (!value) value = split_key(key);
9908f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  if ((toys.optflags & FLAG_w) && !value) {
10070a84a356b1c56743618362867b9300007d11998Rob Landley    error_msg("'%s' not key=value", key);
101e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
102e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    return;
10397c2c1eba507d10005e305098c3fc21b1472c97eRob Landley  }
104f272df9e821e00afb962a62556318cecfcd694aeRob Landley
10508f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  path = xmprintf("/proc/sys/%s", key);
106e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  replace_char(path, '.', '/');
107e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  // Note: failure to assign to a non-leaf node suppresses the display.
10808f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  if (!(value && (!write_key(path, key, value) || (toys.optflags & FLAG_q)))) {
10908f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley    if (!access(path, R_OK)) dirtree_read(path, do_show_keys);
11008f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley    else key_error(key);
11108f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley  }
112e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  free(path);
11397c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
11497c2c1eba507d10005e305098c3fc21b1472c97eRob Landley
11597c2c1eba507d10005e305098c3fc21b1472c97eRob Landleyvoid sysctl_main()
11697c2c1eba507d10005e305098c3fc21b1472c97eRob Landley{
117e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  char **args = 0;
118e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
119e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  // Display all keys
120e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys);
121e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
122e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  // read file
123e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  else if (toys.optflags & FLAG_p) {
124e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    FILE *fp = xfopen(*toys.optargs ? *toys.optargs : "/etc/sysctl.conf", "r");
125e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    size_t len;
126e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
12708f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley    for (;;) {
12808f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      char *line = 0, *key, *val;
129e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
13008f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      if (-1 == (len = getline(&line, &len, fp))) break;
13108f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      key = line;
132e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      while (isspace(*key)) key++;
133e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      if (*key == '#' || *key == ';' || !*key) continue;
13408f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      while (len && isspace(line[len-1])) line[--len] = 0;
135e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      if (!(val = split_key(line))) {
13608f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley        error_msg("'%s' not key=value", line);
137e973d23094883ad66ec24247cb95dbe65db1324eRob Landley        continue;
138e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      }
139e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
14008f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      // Trim whitespace around =
141e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      len = (val-line)-1;
142e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      while (len && isspace(line[len-1])) line[--len] = 0;
143e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      while (isspace(*val)) val++;;
144e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
145e973d23094883ad66ec24247cb95dbe65db1324eRob Landley      process_key(key, val);
14608f2d7d333f1a52ad48bcdc1c2ec1387b9053784Rob Landley      free(line);
14797c2c1eba507d10005e305098c3fc21b1472c97eRob Landley    }
148e973d23094883ad66ec24247cb95dbe65db1324eRob Landley    fclose(fp);
149e973d23094883ad66ec24247cb95dbe65db1324eRob Landley
150e973d23094883ad66ec24247cb95dbe65db1324eRob Landley  // Loop through arguments, displaying or assigning as appropriate
1518941e5fef58025591b7441372d486cf5de46dd39Rob Landley  } else {
1528941e5fef58025591b7441372d486cf5de46dd39Rob Landley    if (!*toys.optargs) help_exit(0);
1538941e5fef58025591b7441372d486cf5de46dd39Rob Landley    for (args = toys.optargs; *args; args++) process_key(*args, 0);
1548941e5fef58025591b7441372d486cf5de46dd39Rob Landley  }
15597c2c1eba507d10005e305098c3fc21b1472c97eRob Landley}
156