1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#define FOR_sysctl
27#include "toys.h"
28
29
30static char *split_key(char *key)
31{
32 char *value = strchr(key, '=');
33
34 if (value) *(value++)=0;
35
36 return value;
37}
38
39static void replace_char(char *str, char old, char new)
40{
41 for (; *str; str++) if (*str == old) *str = new;
42}
43
44static 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
51static 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
67static int do_show_keys(struct dirtree *dt)
68{
69 char *path, *data, *key;
70
71 if (!dirtree_notdotdot(dt)) return 0;
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, '/', '.');
77 if (!data) key_error(key);
78 else {
79
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
94static 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", key);
101
102 return;
103 }
104
105 path = xmprintf("/proc/sys/%s", key);
106 replace_char(path, '.', '/');
107
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
115void sysctl_main()
116{
117 char **args = 0;
118
119
120 if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys);
121
122
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
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
151 } else {
152 if (!*toys.optargs) help_exit("Needs 1 arg");
153 for (args = toys.optargs; *args; args++) process_key(*args, 0);
154 }
155}
156