OSDN Git Service

Promote mix
[android-x86/external-toybox.git] / toys / other / sysctl.c
1 /* sysctl.c - A utility to read and manipulate the sysctl parameters.
2  *
3  * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com>
4  * Copyright 2014 Kyungwan Han <asura321@gmail.com>
5  *
6  * No Standard
7  
8 USE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_USR|TOYFLAG_BIN))
9
10 config SYSCTL
11   bool "sysctl"
12   default y
13   help
14     usage: sysctl [-aAeNnqw] [-p [FILE] | KEY[=VALUE]...]
15
16     Read/write system control data (under /proc/sys).
17
18     -a,A        Show all values
19     -e  Don't warn about unknown keys
20     -N  Don't print key values
21     -n  Don't print key names
22     -p [FILE]   Read values from FILE (default /etc/sysctl.conf)
23     -q  Don't show value after write
24     -w  Only write values (object to reading)
25 */
26 #define FOR_sysctl
27 #include "toys.h"
28
29 // Null terminate at =, return value
30 static char *split_key(char *key)
31 {
32   char *value = strchr(key, '=');
33
34   if (value) *(value++)=0;
35
36   return value;
37 }
38
39 static void replace_char(char *str, char old, char new)
40 {
41   for (; *str; str++) if (*str == old) *str = new;
42 }
43
44 static void key_error(char *key)
45 {
46   if (errno == ENOENT) {
47     if (!(toys.optflags & FLAG_e)) error_msg("unknown key '%s'", key);
48   } else perror_msg("key '%s'", key);
49 }
50
51 static int write_key(char *path, char *key, char *value)
52 {
53   int fd = open(path, O_WRONLY);;
54
55   if (fd < 0) {
56     key_error(key);
57
58     return 0;
59   }
60   xwrite(fd, value, strlen(value));
61   xclose(fd);
62
63   return 1;
64 }
65
66 // Display all keys under a path
67 static int do_show_keys(struct dirtree *dt)
68 {
69   char *path, *data, *key;
70
71   if (!dirtree_notdotdot(dt)) return 0; // Skip . and ..
72   if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE;
73
74   path = dirtree_path(dt, 0);
75   data = readfile(path, 0, 0);
76   replace_char(key = path + 10, '/', '.'); // skip "/proc/sys/"
77   if (!data) key_error(key);
78   else {
79     // Print the parts that aren't switched off by flags.
80     if (!(toys.optflags & FLAG_n)) xprintf("%s", key);
81     if (!(toys.optflags & (FLAG_N|FLAG_n))) xprintf(" = ");
82     for (key = data+strlen(data); key > data && isspace(*--key); *key = 0);
83     if (!(toys.optflags & FLAG_N)) xprintf("%s", data);
84     if ((toys.optflags & (FLAG_N|FLAG_n)) != (FLAG_N|FLAG_n)) xputc('\n');
85   }
86
87   free(data);
88   free(path);
89
90   return 0;
91 }
92
93 // Read/write entries under a key. Accepts "key=value" in key if !value
94 static void process_key(char *key, char *value)
95 {
96   char *path;
97
98   if (!value) value = split_key(key);
99   if ((toys.optflags & FLAG_w) && !value) {
100     error_msg("'%s' not key=value");
101
102     return;
103   }
104
105   path = xmprintf("/proc/sys/%s", key);
106   replace_char(path, '.', '/');
107   // Note: failure to assign to a non-leaf node suppresses the display.
108   if (!(value && (!write_key(path, key, value) || (toys.optflags & FLAG_q)))) {
109     if (!access(path, R_OK)) dirtree_read(path, do_show_keys);
110     else key_error(key);
111   }
112   free(path);
113 }
114
115 void sysctl_main()
116 {
117   char **args = 0;
118
119   // Display all keys
120   if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys);
121
122   // read file
123   else if (toys.optflags & FLAG_p) {
124     FILE *fp = xfopen(*toys.optargs ? *toys.optargs : "/etc/sysctl.conf", "r");
125     size_t len;
126
127     for (;;) {
128       char *line = 0, *key, *val;
129
130       if (-1 == (len = getline(&line, &len, fp))) break;
131       key = line;
132       while (isspace(*key)) key++;
133       if (*key == '#' || *key == ';' || !*key) continue;
134       while (len && isspace(line[len-1])) line[--len] = 0;
135       if (!(val = split_key(line))) {
136         error_msg("'%s' not key=value", line);
137         continue;
138       }
139
140       // Trim whitespace around =
141       len = (val-line)-1;
142       while (len && isspace(line[len-1])) line[--len] = 0;
143       while (isspace(*val)) val++;;
144
145       process_key(key, val);
146       free(line);
147     }
148     fclose(fp);
149
150   // Loop through arguments, displaying or assigning as appropriate
151   } else for (args = toys.optargs; *args; args++) process_key(*args, 0);
152 }