diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-29 02:23:16 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-29 02:23:16 +0000 |
commit | 038fe447138aa04d1295cde2e597ec3497ce9214 (patch) | |
tree | a031ea2aff609f191920ddb76bf40035faea423d | |
parent | 5a6617acb81020a3becd91bd21f427157d7c9dcd (diff) | |
download | busybox-w32-038fe447138aa04d1295cde2e597ec3497ce9214.tar.gz busybox-w32-038fe447138aa04d1295cde2e597ec3497ce9214.tar.bz2 busybox-w32-038fe447138aa04d1295cde2e597ec3497ce9214.zip |
sysctl: move code around to get rid of forward references.
(incidentally it helps gcc to make code smaller)
-rw-r--r-- | procps/sysctl.c | 209 |
1 files changed, 101 insertions, 108 deletions
diff --git a/procps/sysctl.c b/procps/sysctl.c index dce264dac..d0ff20ec7 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c | |||
@@ -7,20 +7,12 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | * | 8 | * |
9 | * Changelog: | 9 | * Changelog: |
10 | * v1.01: | 10 | * v1.01 - added -p <preload> to preload values from a file |
11 | * - added -p <preload> to preload values from a file | 11 | * v1.01.1 - busybox applet aware by <solar@gentoo.org> |
12 | * v1.01.1 | ||
13 | * - busybox applet aware by <solar@gentoo.org> | ||
14 | * | ||
15 | */ | 12 | */ |
16 | 13 | ||
17 | #include "libbb.h" | 14 | #include "libbb.h" |
18 | 15 | ||
19 | static int sysctl_act_on_setting(char *setting); | ||
20 | static int sysctl_display_all(const char *path); | ||
21 | static int sysctl_handle_preload_file(const char *filename); | ||
22 | static void sysctl_dots_to_slashes(char *name); | ||
23 | |||
24 | enum { | 16 | enum { |
25 | FLAG_SHOW_KEYS = 1 << 0, | 17 | FLAG_SHOW_KEYS = 1 << 0, |
26 | FLAG_SHOW_KEY_ERRORS = 1 << 1, | 18 | FLAG_SHOW_KEY_ERRORS = 1 << 1, |
@@ -29,67 +21,52 @@ enum { | |||
29 | FLAG_PRELOAD_FILE = 1 << 4, | 21 | FLAG_PRELOAD_FILE = 1 << 4, |
30 | FLAG_WRITE = 1 << 5, | 22 | FLAG_WRITE = 1 << 5, |
31 | }; | 23 | }; |
24 | #define OPTION_STR "neAapw" | ||
32 | 25 | ||
33 | int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 26 | static void sysctl_dots_to_slashes(char *name) |
34 | int sysctl_main(int argc UNUSED_PARAM, char **argv) | ||
35 | { | ||
36 | int retval; | ||
37 | int opt; | ||
38 | |||
39 | opt = getopt32(argv, "+neAapw"); /* '+' - stop on first non-option */ | ||
40 | argv += optind; | ||
41 | opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); | ||
42 | option_mask32 = opt; | ||
43 | |||
44 | if (opt & FLAG_PRELOAD_FILE) { | ||
45 | option_mask32 |= FLAG_WRITE; | ||
46 | /* xchdir("/proc/sys") is inside */ | ||
47 | return sysctl_handle_preload_file(*argv ? *argv : "/etc/sysctl.conf"); | ||
48 | } | ||
49 | xchdir("/proc/sys"); | ||
50 | /* xchroot(".") - if you are paranoid */ | ||
51 | if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) { | ||
52 | return sysctl_display_all("."); | ||
53 | } | ||
54 | |||
55 | retval = 0; | ||
56 | while (*argv) { | ||
57 | sysctl_dots_to_slashes(*argv); | ||
58 | retval |= sysctl_display_all(*argv); | ||
59 | argv++; | ||
60 | } | ||
61 | |||
62 | return retval; | ||
63 | } | ||
64 | |||
65 | /* Set sysctl's from a conf file. Format example: | ||
66 | * # Controls IP packet forwarding | ||
67 | * net.ipv4.ip_forward = 0 | ||
68 | */ | ||
69 | static int sysctl_handle_preload_file(const char *filename) | ||
70 | { | 27 | { |
71 | char *token[2]; | 28 | char *cptr, *last_good, *end; |
72 | parser_t *parser; | ||
73 | 29 | ||
74 | parser = config_open(filename); | 30 | /* Convert minimum number of '.' to '/' so that |
75 | /* Must do it _after_ config_open(): */ | 31 | * we end up with existing file's name. |
76 | xchdir("/proc/sys"); | 32 | * |
77 | /* xchroot(".") - if you are paranoid */ | 33 | * Example from bug 3894: |
34 | * net.ipv4.conf.eth0.100.mc_forwarding -> | ||
35 | * net/ipv4/conf/eth0.100/mc_forwarding | ||
36 | * NB: net/ipv4/conf/eth0/mc_forwarding *also exists*, | ||
37 | * therefore we must start from the end, and if | ||
38 | * we replaced even one . -> /, start over again, | ||
39 | * but never replace dots before the position | ||
40 | * where last replacement occurred. | ||
41 | * | ||
42 | * Another bug we later had is that | ||
43 | * net.ipv4.conf.eth0.100 | ||
44 | * (without .mc_forwarding) was mishandled. | ||
45 | * | ||
46 | * To set up testing: modprobe 8021q; vconfig add eth0 100 | ||
47 | */ | ||
48 | end = name + strlen(name); | ||
49 | last_good = name - 1; | ||
50 | *end = '.'; /* trick the loop into trying full name too */ | ||
78 | 51 | ||
79 | //TODO: ';' is comment char too | 52 | again: |
80 | //TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value | 53 | cptr = end; |
81 | // (but _whitespace_ from ends should be trimmed first (and we do it right)) | 54 | while (cptr > last_good) { |
82 | //TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1") | 55 | if (*cptr == '.') { |
83 | while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { | 56 | *cptr = '\0'; |
84 | sysctl_dots_to_slashes(token[0]); | 57 | //bb_error_msg("trying:'%s'", name); |
85 | /* Save ~4 bytes by using parser internals */ | 58 | if (access(name, F_OK) == 0) { |
86 | /* parser->line is big enough for sprintf */ | 59 | if (cptr != end) /* prevent trailing '/' */ |
87 | sprintf(parser->line, "%s=%s", token[0], token[1]); | 60 | *cptr = '/'; |
88 | sysctl_display_all(parser->line); | 61 | //bb_error_msg("replaced:'%s'", name); |
62 | last_good = cptr; | ||
63 | goto again; | ||
64 | } | ||
65 | *cptr = '.'; | ||
66 | } | ||
67 | cptr--; | ||
89 | } | 68 | } |
90 | if (ENABLE_FEATURE_CLEAN_UP) | 69 | *end = '\0'; |
91 | config_close(parser); | ||
92 | return 0; | ||
93 | } | 70 | } |
94 | 71 | ||
95 | static int sysctl_act_on_setting(char *setting) | 72 | static int sysctl_act_on_setting(char *setting) |
@@ -186,7 +163,7 @@ static int sysctl_act_on_setting(char *setting) | |||
186 | return retval; | 163 | return retval; |
187 | } | 164 | } |
188 | 165 | ||
189 | static int sysctl_display_all(const char *path) | 166 | static int sysctl_act_recursive(const char *path) |
190 | { | 167 | { |
191 | DIR *dirp; | 168 | DIR *dirp; |
192 | struct stat buf; | 169 | struct stat buf; |
@@ -204,7 +181,7 @@ static int sysctl_display_all(const char *path) | |||
204 | if (next == NULL) | 181 | if (next == NULL) |
205 | continue; /* d_name is "." or ".." */ | 182 | continue; /* d_name is "." or ".." */ |
206 | /* if path was ".", drop "./" prefix: */ | 183 | /* if path was ".", drop "./" prefix: */ |
207 | retval |= sysctl_display_all((next[0] == '.' && next[1] == '/') ? | 184 | retval |= sysctl_act_recursive((next[0] == '.' && next[1] == '/') ? |
208 | next + 2 : next); | 185 | next + 2 : next); |
209 | free(next); | 186 | free(next); |
210 | } | 187 | } |
@@ -218,48 +195,64 @@ static int sysctl_display_all(const char *path) | |||
218 | return retval; | 195 | return retval; |
219 | } | 196 | } |
220 | 197 | ||
221 | static void sysctl_dots_to_slashes(char *name) | 198 | /* Set sysctl's from a conf file. Format example: |
199 | * # Controls IP packet forwarding | ||
200 | * net.ipv4.ip_forward = 0 | ||
201 | */ | ||
202 | static int sysctl_handle_preload_file(const char *filename) | ||
222 | { | 203 | { |
223 | char *cptr, *last_good, *end; | 204 | char *token[2]; |
205 | parser_t *parser; | ||
224 | 206 | ||
225 | /* Convert minimum number of '.' to '/' so that | 207 | parser = config_open(filename); |
226 | * we end up with existing file's name. | 208 | /* Must do it _after_ config_open(): */ |
227 | * | 209 | xchdir("/proc/sys"); |
228 | * Example from bug 3894: | 210 | /* xchroot(".") - if you are paranoid */ |
229 | * net.ipv4.conf.eth0.100.mc_forwarding -> | ||
230 | * net/ipv4/conf/eth0.100/mc_forwarding | ||
231 | * NB: net/ipv4/conf/eth0/mc_forwarding *also exists*, | ||
232 | * therefore we must start from the end, and if | ||
233 | * we replaced even one . -> /, start over again, | ||
234 | * but never replace dots before the position | ||
235 | * where last replacement occurred. | ||
236 | * | ||
237 | * Another bug we later had is that | ||
238 | * net.ipv4.conf.eth0.100 | ||
239 | * (without .mc_forwarding) was mishandled. | ||
240 | * | ||
241 | * To set up testing: modprobe 8021q; vconfig add eth0 100 | ||
242 | */ | ||
243 | end = name + strlen(name); | ||
244 | last_good = name - 1; | ||
245 | *end = '.'; /* trick the loop into trying full name too */ | ||
246 | 211 | ||
247 | again: | 212 | //TODO: ';' is comment char too |
248 | cptr = end; | 213 | //TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value |
249 | while (cptr > last_good) { | 214 | // (but _whitespace_ from ends should be trimmed first (and we do it right)) |
250 | if (*cptr == '.') { | 215 | //TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1") |
251 | *cptr = '\0'; | 216 | while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { |
252 | //bb_error_msg("trying:'%s'", name); | 217 | sysctl_dots_to_slashes(token[0]); |
253 | if (access(name, F_OK) == 0) { | 218 | /* Save ~4 bytes by using parser internals */ |
254 | if (cptr != end) /* prevent trailing '/' */ | 219 | /* parser->line is big enough for sprintf */ |
255 | *cptr = '/'; | 220 | sprintf(parser->line, "%s=%s", token[0], token[1]); |
256 | //bb_error_msg("replaced:'%s'", name); | 221 | sysctl_act_recursive(parser->line); |
257 | last_good = cptr; | ||
258 | goto again; | ||
259 | } | ||
260 | *cptr = '.'; | ||
261 | } | ||
262 | cptr--; | ||
263 | } | 222 | } |
264 | *end = '\0'; | 223 | if (ENABLE_FEATURE_CLEAN_UP) |
224 | config_close(parser); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
229 | int sysctl_main(int argc UNUSED_PARAM, char **argv) | ||
230 | { | ||
231 | int retval; | ||
232 | int opt; | ||
233 | |||
234 | opt = getopt32(argv, "+" OPTION_STR); /* '+' - stop on first non-option */ | ||
235 | argv += optind; | ||
236 | opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); | ||
237 | option_mask32 = opt; | ||
238 | |||
239 | if (opt & FLAG_PRELOAD_FILE) { | ||
240 | option_mask32 |= FLAG_WRITE; | ||
241 | /* xchdir("/proc/sys") is inside */ | ||
242 | return sysctl_handle_preload_file(*argv ? *argv : "/etc/sysctl.conf"); | ||
243 | } | ||
244 | xchdir("/proc/sys"); | ||
245 | /* xchroot(".") - if you are paranoid */ | ||
246 | if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) { | ||
247 | return sysctl_act_recursive("."); | ||
248 | } | ||
249 | |||
250 | retval = 0; | ||
251 | while (*argv) { | ||
252 | sysctl_dots_to_slashes(*argv); | ||
253 | retval |= sysctl_act_recursive(*argv); | ||
254 | argv++; | ||
255 | } | ||
256 | |||
257 | return retval; | ||
265 | } | 258 | } |