diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/getopt32.c | 71 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 17 |
2 files changed, 54 insertions, 34 deletions
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 513415894..b2b4de8cb 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | 9 | #if ENABLE_LONG_OPTS |
10 | # include <getopt.h> | 10 | # include <getopt.h> |
11 | #endif | 11 | #endif |
12 | #include "libbb.h" | 12 | #include "libbb.h" |
@@ -99,17 +99,18 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
99 | "!" Report bad option, missing required options, | 99 | "!" Report bad option, missing required options, |
100 | inconsistent options with all-ones return value (instead of abort). | 100 | inconsistent options with all-ones return value (instead of abort). |
101 | 101 | ||
102 | const char *applet_long_options | 102 | uint32_t |
103 | getopt32long(char **argv, const char *applet_opts, const char *logopts...) | ||
103 | 104 | ||
104 | This struct allows you to define long options: | 105 | This allows you to define long options: |
105 | 106 | ||
106 | static const char applet_longopts[] ALIGN1 = | 107 | static const char applet_longopts[] ALIGN1 = |
107 | //"name\0" has_arg val | 108 | //"name\0" has_arg val |
108 | "verbose\0" No_argument "v" | 109 | "verbose\0" No_argument "v" |
109 | ; | 110 | ; |
110 | applet_long_options = applet_longopts; | 111 | opt = getopt32long(argv, applet_opts, applet_longopts, ...); |
111 | 112 | ||
112 | The last member of struct option (val) typically is set to | 113 | The last element (val) typically is set to |
113 | matching short option from applet_opts. If there is no matching | 114 | matching short option from applet_opts. If there is no matching |
114 | char in applet_opts, then: | 115 | char in applet_opts, then: |
115 | - return bit has next position after short options | 116 | - return bit has next position after short options |
@@ -317,20 +318,21 @@ typedef struct { | |||
317 | int *counter; | 318 | int *counter; |
318 | } t_complementary; | 319 | } t_complementary; |
319 | 320 | ||
320 | /* You can set applet_long_options for parse called long options */ | 321 | uint32_t option_mask32; |
321 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | 322 | |
323 | #if ENABLE_LONG_OPTS | ||
322 | static const struct option bb_null_long_options[1] = { | 324 | static const struct option bb_null_long_options[1] = { |
323 | { 0, 0, 0, 0 } | 325 | { 0, 0, 0, 0 } |
324 | }; | 326 | }; |
325 | const char *applet_long_options; | 327 | #else |
328 | #define vgetopt32(argv,applet_opts,applet_long_options,p) \ | ||
329 | vgetopt32(argv,applet_opts,p) | ||
326 | #endif | 330 | #endif |
327 | 331 | ||
328 | uint32_t option_mask32; | ||
329 | |||
330 | /* Please keep getopt32 free from xmalloc */ | 332 | /* Please keep getopt32 free from xmalloc */ |
331 | 333 | ||
332 | uint32_t FAST_FUNC | 334 | static uint32_t |
333 | getopt32(char **argv, const char *applet_opts, ...) | 335 | vgetopt32(char **argv, const char *applet_opts, const char *applet_long_options, va_list p) |
334 | { | 336 | { |
335 | int argc; | 337 | int argc; |
336 | unsigned flags = 0; | 338 | unsigned flags = 0; |
@@ -340,8 +342,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
340 | int c; | 342 | int c; |
341 | const unsigned char *s; | 343 | const unsigned char *s; |
342 | t_complementary *on_off; | 344 | t_complementary *on_off; |
343 | va_list p; | 345 | #if ENABLE_LONG_OPTS |
344 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | ||
345 | const struct option *l_o; | 346 | const struct option *l_o; |
346 | struct option *long_options = (struct option *) &bb_null_long_options; | 347 | struct option *long_options = (struct option *) &bb_null_long_options; |
347 | #endif | 348 | #endif |
@@ -356,8 +357,6 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
356 | /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ | 357 | /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ |
357 | argc = 1 + string_array_len(argv + 1); | 358 | argc = 1 + string_array_len(argv + 1); |
358 | 359 | ||
359 | va_start(p, applet_opts); | ||
360 | |||
361 | on_off = complementary; | 360 | on_off = complementary; |
362 | memset(on_off, 0, sizeof(complementary)); | 361 | memset(on_off, 0, sizeof(complementary)); |
363 | 362 | ||
@@ -394,7 +393,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
394 | c++; | 393 | c++; |
395 | } | 394 | } |
396 | 395 | ||
397 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | 396 | #if ENABLE_LONG_OPTS |
398 | if (applet_long_options) { | 397 | if (applet_long_options) { |
399 | const char *optstr; | 398 | const char *optstr; |
400 | unsigned i, count; | 399 | unsigned i, count; |
@@ -433,12 +432,8 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
433 | c++; | 432 | c++; |
434 | next_long: ; | 433 | next_long: ; |
435 | } | 434 | } |
436 | /* Make it unnecessary to clear applet_long_options | ||
437 | * by hand after each call to getopt32 | ||
438 | */ | ||
439 | applet_long_options = NULL; | ||
440 | } | 435 | } |
441 | #endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ | 436 | #endif /* ENABLE_LONG_OPTS */ |
442 | 437 | ||
443 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { | 438 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { |
444 | t_complementary *pair; | 439 | t_complementary *pair; |
@@ -517,9 +512,9 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
517 | } | 512 | } |
518 | s--; | 513 | s--; |
519 | } | 514 | } |
520 | opt_complementary = NULL; | ||
521 | va_end(p); | ||
522 | 515 | ||
516 | /* Make it unnecessary to clear it by hand after each getopt32 call */ | ||
517 | opt_complementary = NULL; | ||
523 | /* In case getopt32 was already called: | 518 | /* In case getopt32 was already called: |
524 | * reset the libc getopt() function, which keeps internal state. | 519 | * reset the libc getopt() function, which keeps internal state. |
525 | * run_nofork_applet() does this, but we might end up here | 520 | * run_nofork_applet() does this, but we might end up here |
@@ -531,7 +526,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
531 | * "fake" short options, like this one: | 526 | * "fake" short options, like this one: |
532 | * wget $'-\203' "Test: test" http://kernel.org/ | 527 | * wget $'-\203' "Test: test" http://kernel.org/ |
533 | * (supposed to act as --header, but doesn't) */ | 528 | * (supposed to act as --header, but doesn't) */ |
534 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | 529 | #if ENABLE_LONG_OPTS |
535 | while ((c = getopt_long(argc, argv, applet_opts, | 530 | while ((c = getopt_long(argc, argv, applet_opts, |
536 | long_options, NULL)) != -1) { | 531 | long_options, NULL)) != -1) { |
537 | #else | 532 | #else |
@@ -592,3 +587,29 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
592 | bb_show_usage(); | 587 | bb_show_usage(); |
593 | return (int32_t)-1; | 588 | return (int32_t)-1; |
594 | } | 589 | } |
590 | |||
591 | uint32_t FAST_FUNC | ||
592 | getopt32(char **argv, const char *applet_opts, ...) | ||
593 | { | ||
594 | uint32_t opt; | ||
595 | va_list p; | ||
596 | |||
597 | va_start(p, applet_opts); | ||
598 | opt = vgetopt32(argv, applet_opts, NULL, p); | ||
599 | va_end(p); | ||
600 | return opt; | ||
601 | } | ||
602 | |||
603 | #if ENABLE_LONG_OPTS | ||
604 | uint32_t FAST_FUNC | ||
605 | getopt32long(char **argv, const char *applet_opts, const char *longopts, ...) | ||
606 | { | ||
607 | uint32_t opt; | ||
608 | va_list p; | ||
609 | |||
610 | va_start(p, longopts); | ||
611 | opt = vgetopt32(argv, applet_opts, longopts, p); | ||
612 | va_end(p); | ||
613 | return opt; | ||
614 | } | ||
615 | #endif | ||
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index e55847f93..15c92a7cd 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -45,14 +45,15 @@ static void jump(void) | |||
45 | { | 45 | { |
46 | /* Special case. We arrive here if NOFORK applet | 46 | /* Special case. We arrive here if NOFORK applet |
47 | * calls xfunc, which then decides to die. | 47 | * calls xfunc, which then decides to die. |
48 | * We don't die, but jump instead back to caller. | 48 | * We don't die, but instead jump back to caller. |
49 | * NOFORK applets still cannot carelessly call xfuncs: | 49 | * NOFORK applets still cannot carelessly call xfuncs: |
50 | * p = xmalloc(10); | 50 | * p = xmalloc(10); |
51 | * q = xmalloc(10); // BUG! if this dies, we leak p! | 51 | * q = xmalloc(10); // BUG! if this dies, we leak p! |
52 | */ | 52 | */ |
53 | /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0). | 53 | /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0). |
54 | * This works because exitcodes are bytes, | 54 | * This works because exitcodes are bytes, |
55 | * run_nofork_applet() ensures that by "& 0xff" */ | 55 | * run_nofork_applet() ensures that by "& 0xff" |
56 | */ | ||
56 | longjmp(die_jmp, xfunc_error_retval | 0x100); | 57 | longjmp(die_jmp, xfunc_error_retval | 0x100); |
57 | } | 58 | } |
58 | 59 | ||
@@ -92,12 +93,12 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
92 | 93 | ||
93 | logmode = LOGMODE_STDIO; | 94 | logmode = LOGMODE_STDIO; |
94 | xfunc_error_retval = EXIT_FAILURE; | 95 | xfunc_error_retval = EXIT_FAILURE; |
95 | /* In case getopt() or getopt32() was already called: | 96 | /* In case getopt() was already called: |
96 | * reset the libc getopt() function, which keeps internal state. | 97 | * reset the libc getopt() function, which keeps internal state. |
98 | * (getopt32() does it itself, but getopt() doesn't (and can't)) | ||
97 | */ | 99 | */ |
98 | GETOPT_RESET(); | 100 | GETOPT_RESET(); |
99 | //? applet_long_options = NULL; | 101 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ |
100 | //? opt_complementary = NULL; | ||
101 | 102 | ||
102 | argc = string_array_len(argv); | 103 | argc = string_array_len(argv); |
103 | 104 | ||
@@ -122,8 +123,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
122 | restore_nofork_data(&old); | 123 | restore_nofork_data(&old); |
123 | /* Other globals can be simply reset to defaults */ | 124 | /* Other globals can be simply reset to defaults */ |
124 | GETOPT_RESET(); | 125 | GETOPT_RESET(); |
125 | //? applet_long_options = NULL; | 126 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ |
126 | //? opt_complementary = NULL; | ||
127 | 127 | ||
128 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | 128 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ |
129 | } | 129 | } |
@@ -138,8 +138,7 @@ void FAST_FUNC run_noexec_applet_and_exit(int a, const char *name, char **argv) | |||
138 | xfunc_error_retval = EXIT_FAILURE; | 138 | xfunc_error_retval = EXIT_FAILURE; |
139 | die_func = NULL; | 139 | die_func = NULL; |
140 | GETOPT_RESET(); | 140 | GETOPT_RESET(); |
141 | //? applet_long_options = NULL; | 141 | /* opt_complementary = NULL; - cleared by each getopt32() call anyway */ |
142 | //? opt_complementary = NULL; | ||
143 | 142 | ||
144 | //TODO: think pidof, pgrep, pkill! | 143 | //TODO: think pidof, pgrep, pkill! |
145 | //set_task_comm() makes our pidof find NOEXECs (e.g. "yes >/dev/null"), | 144 | //set_task_comm() makes our pidof find NOEXECs (e.g. "yes >/dev/null"), |