diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-08 16:38:18 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-08 17:09:40 +0200 |
commit | 036585a911a5fe6c2cd77b808dd9150500f37272 (patch) | |
tree | aa7c65b4d09c74642f622a1ef5da982d6ed4940a /libbb | |
parent | 00677b5e35dd97f415f0b0bef25b55865f55ab33 (diff) | |
download | busybox-w32-036585a911a5fe6c2cd77b808dd9150500f37272.tar.gz busybox-w32-036585a911a5fe6c2cd77b808dd9150500f37272.tar.bz2 busybox-w32-036585a911a5fe6c2cd77b808dd9150500f37272.zip |
getopt32: remove applet_long_options
FEATURE_GETOPT_LONG made dependent on LONG_OPTS.
The folloving options are removed, now LONG_OPTS enables long options
for affected applets:
FEATURE_ENV_LONG_OPTIONS FEATURE_EXPAND_LONG_OPTIONS
FEATURE_UNEXPAND_LONG_OPTIONS FEATURE_MKDIR_LONG_OPTIONS
FEATURE_MV_LONG_OPTIONS FEATURE_RMDIR_LONG_OPTIONS
FEATURE_ADDGROUP_LONG_OPTIONS FEATURE_ADDUSER_LONG_OPTIONS
FEATURE_HWCLOCK_LONG_OPTIONS FEATURE_NSENTER_LONG_OPTS
FEATURE_CHCON_LONG_OPTIONS FEATURE_RUNCON_LONG_OPTIONS
They either had a small number of long options, or their long options are
essential.
Example: upstream addgroup and adduser have ONLY longopts,
we should probably go further and get rid
of non-standard short options.
To this end, make addgroup and adduser "select LONG_OPTS".
We had this breakage caused by us even in our own package!
#if ENABLE_LONG_OPTS || !ENABLE_ADDGROUP
/* We try to use --gid, not -g, because "standard" addgroup
* has no short option -g, it has only long --gid.
*/
argv[1] = (char*)"--gid";
#else
/* Breaks if system in fact does NOT use busybox addgroup */
argv[1] = (char*)"-g";
#endif
xargs: its lone longopt no longer depends on DESKTOP, only on LONG_OPTS.
hwclock TODO: get rid of incompatible -t, -l aliases to --systz, --localtime
Shorten help texts by omitting long option when short opt alternative exists.
Reduction of size comes from the fact that store of an immediate
(an address of longopts) to a fixed address (global variable)
is a longer insn than pushing that immediate or passing it in a register.
This effect is CPU-agnostic.
function old new delta
getopt32 1350 22 -1328
vgetopt32 - 1318 +1318
getopt32long - 24 +24
tftpd_main 562 567 +5
scan_recursive 376 380 +4
collect_cpu 545 546 +1
date_main 1096 1095 -1
hostname_main 262 259 -3
uname_main 259 255 -4
setpriv_main 362 358 -4
rmdir_main 191 187 -4
mv_main 562 558 -4
ipcalc_main 548 544 -4
ifenslave_main 641 637 -4
gzip_main 192 188 -4
gunzip_main 77 73 -4
fsfreeze_main 81 77 -4
flock_main 318 314 -4
deluser_main 337 333 -4
cp_main 374 370 -4
chown_main 175 171 -4
applet_long_options 4 - -4
xargs_main 894 889 -5
wget_main 2540 2535 -5
udhcpc_main 2767 2762 -5
touch_main 436 431 -5
tar_main 1014 1009 -5
start_stop_daemon_main 1033 1028 -5
sed_main 682 677 -5
script_main 1082 1077 -5
run_parts_main 330 325 -5
rtcwake_main 459 454 -5
od_main 2169 2164 -5
nl_main 201 196 -5
modprobe_main 773 768 -5
mkdir_main 160 155 -5
ls_main 568 563 -5
install_main 773 768 -5
hwclock_main 411 406 -5
getopt_main 622 617 -5
fstrim_main 256 251 -5
env_main 198 193 -5
dumpleases_main 635 630 -5
dpkg_main 3991 3986 -5
diff_main 1355 1350 -5
cryptpw_main 233 228 -5
cpio_main 593 588 -5
conspy_main 1135 1130 -5
chpasswd_main 313 308 -5
adduser_main 887 882 -5
addgroup_main 416 411 -5
ftpgetput_main 351 345 -6
get_terminal_width_height 242 234 -8
expand_main 690 680 -10
static.expand_longopts 18 - -18
static.unexpand_longopts 27 - -27
mkdir_longopts 28 - -28
env_longopts 30 - -30
static.ifenslave_longopts 34 - -34
mv_longopts 46 - -46
static.rmdir_longopts 48 - -48
packed_usage 31739 31687 -52
------------------------------------------------------------------------------
(add/remove: 2/8 grow/shrink: 3/49 up/down: 1352/-1840) Total: -488 bytes
text data bss dec hex filename
915681 485 6880 923046 e15a6 busybox_old
915428 485 6876 922789 e14a5 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
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"), |