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