Mercurial > hg > toybox
annotate toys/pending/sysctl.c @ 1283:55de00e9daf4 draft
Cleanup pass on sysctl.
Not heavily tested yet but should be finished at the design level.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 13 May 2014 19:45:01 -0500 |
parents | c99912c6bc09 |
children | 5c1bd5b94541 |
rev | line source |
---|---|
1281 | 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 n | |
13 help | |
1283 | 14 usage: sysctl [-aAeNnqw] [-p [FILE] | KEY[=VALUE]...] |
1281 | 15 |
1283 | 16 Read/write system control data (under /proc/sys). |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
17 |
1283 | 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) | |
1281 | 25 */ |
26 #define FOR_sysctl | |
27 #include "toys.h" | |
28 | |
1283 | 29 // Null terminate at =, return value |
30 static char *split_key(char *key) | |
1281 | 31 { |
1283 | 32 char *value = strchr(key, '='); |
1281 | 33 |
1283 | 34 if (value) *(value++)=0; |
35 | |
36 return value; | |
1281 | 37 } |
38 | |
39 static void replace_char(char *str, char old, char new) | |
40 { | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
41 for (; *str; str++) if (*str == old) *str = new; |
1281 | 42 } |
43 | |
1283 | 44 static void key_error(char *key) |
1281 | 45 { |
1283 | 46 if (!(errno == ENOENT && (toys.optflags & FLAG_e))) |
47 perror_msg("key '%s'", key); | |
1281 | 48 } |
49 | |
1283 | 50 static int write_key(char *path, char *key, char *value) |
1281 | 51 { |
1283 | 52 int fd = open(path, O_WRONLY);; |
1281 | 53 |
1283 | 54 if (fd < 0) { |
55 key_error(key); | |
56 | |
57 return 0; | |
1281 | 58 } |
1283 | 59 xwrite(fd, value, strlen(value)); |
60 xclose(fd); | |
1281 | 61 |
1283 | 62 return 1; |
1281 | 63 } |
64 | |
1283 | 65 // Display all keys under a path |
66 static int do_show_keys(struct dirtree *dt) | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
67 { |
1283 | 68 char *path, *data, *key; |
1281 | 69 |
70 if (!dirtree_notdotdot(dt)) return 0; // Skip . and .. | |
1283 | 71 if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE; |
72 | |
73 path = dirtree_path(dt, 0); | |
74 data = readfile(path, 0, 0); | |
75 replace_char(key = path + 10, '/', '.'); // skip "/proc/sys/" | |
76 if (!data) key_error(key); | |
77 else { | |
78 // Print the parts that aren't switched off by flags. | |
79 if (!(toys.optflags & FLAG_n)) xprintf("%s", key); | |
80 if (!(toys.optflags & (FLAG_N|FLAG_n))) xprintf(" = "); | |
81 for (key = data+strlen(data); key > data && isspace(*--key); *key = 0); | |
82 if (!(toys.optflags & FLAG_N)) xprintf("%s", data); | |
83 if ((toys.optflags & (FLAG_N|FLAG_n)) != (FLAG_N|FLAG_n)) xputc('\n'); | |
1281 | 84 } |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
85 |
1283 | 86 free(data); |
87 free(path); | |
88 | |
1281 | 89 return 0; |
90 } | |
91 | |
1283 | 92 // Read/write entries under a key |
93 static void process_key(char *key, char *value) | |
1281 | 94 { |
1283 | 95 char *path, *pattern = "%s/%s/%s"; |
1281 | 96 |
1283 | 97 if ((toys.optflags & FLAG_w) && !value && !strchr(key, '=')) { |
98 error_msg("'%s' not key=value"); | |
99 | |
1281 | 100 return; |
101 } | |
1283 | 102 |
103 path = xmprintf(pattern + 3*!value, "/proc/sys", key, value); | |
104 value = split_key(path); | |
105 replace_char(path, '.', '/'); | |
106 // Note: failure to assign to a non-leaf node suppresses the display. | |
107 if (!(value && (write_key(path, key, value) || (toys.optflags & FLAG_q)))) | |
108 dirtree_read(path, do_show_keys); | |
109 free(path); | |
110 } | |
111 | |
112 void sysctl_main() | |
113 { | |
114 char **args = 0; | |
115 | |
116 // Display all keys | |
117 if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys); | |
118 | |
119 // read file | |
120 else if (toys.optflags & FLAG_p) { | |
121 FILE *fp = xfopen(*toys.optargs ? *toys.optargs : "/etc/sysctl.conf", "r"); | |
122 char *line = 0; | |
123 size_t len; | |
124 | |
125 for (;-1 != (len = getline(&line, &len, fp)); free(line), line = 0) { | |
126 char *key = line, *val; | |
127 | |
128 while (isspace(*key)) key++; | |
129 if (*key == '#' || *key == ';' || !*key) continue; | |
130 if (!(val = split_key(line))) { | |
131 error_msg("'%s' not key=value"); | |
132 continue; | |
133 } | |
134 | |
135 // Trim whitespace off key and value | |
136 while (len && isspace(line[len-1])) line[--len] = 0; | |
137 len = (val-line)-1; | |
138 while (len && isspace(line[len-1])) line[--len] = 0; | |
139 while (isspace(*val)) val++;; | |
140 | |
141 process_key(key, val); | |
1281 | 142 } |
1283 | 143 fclose(fp); |
144 | |
145 // Loop through arguments, displaying or assigning as appropriate | |
146 } else for (args = toys.optargs; *args; args++) process_key(*args, 0); | |
1281 | 147 } |