aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-29 02:23:16 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-29 02:23:16 +0000
commit038fe447138aa04d1295cde2e597ec3497ce9214 (patch)
treea031ea2aff609f191920ddb76bf40035faea423d
parent5a6617acb81020a3becd91bd21f427157d7c9dcd (diff)
downloadbusybox-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.c209
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
19static int sysctl_act_on_setting(char *setting);
20static int sysctl_display_all(const char *path);
21static int sysctl_handle_preload_file(const char *filename);
22static void sysctl_dots_to_slashes(char *name);
23
24enum { 16enum {
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
33int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 26static void sysctl_dots_to_slashes(char *name)
34int 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 */
69static 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
95static int sysctl_act_on_setting(char *setting) 72static 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
189static int sysctl_display_all(const char *path) 166static 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
221static 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 */
202static 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
228int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
229int 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}