From 6bdfbc4cb5470f63d4905e89f89a9829af354316 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 18 Feb 2021 23:30:24 +0100 Subject: libbb: fix '--help' handling in FEATURE_SH_NOFORK=y Most BusyBox applets respond to the '--help' option by printing a usage message. This is normally handled by busybox_main() so applet main routines don't have support for '--help'. In standalone shell mode with FEATURE_SH_NOFORK enabled nofork applets are invoked directly, bypassing busybox_main(). This results in inconsistent handling of '--help': - applets which call getopt() report "unrecognized option '--help'" and print help anyway; - realpath says "--help: No such file or directory" and doesn't print help; - usleep says "invalid number '--help'" and doesn't print help. Avoid inconsistency by checking for '--help' in run_nofork_applet(). Bug found by Ron Yorston. function old new delta show_usage_if_dash_dash_help - 70 +70 run_nofork_applet 347 362 +15 run_applet_no_and_exit 432 365 -67 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 85/-67) Total: 18 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/appletlib.c | 29 +++++++++++++++++++---------- libbb/vfork_daemon_rexec.c | 5 +++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 135d9111d..ece03e7d8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1219,6 +1219,7 @@ void run_noexec_applet_and_exit(int a, const char *name, char **argv) NORETURN F int find_applet_by_name(const char *name) FAST_FUNC; void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC; #endif +void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; #if defined(__linux__) void set_task_comm(const char *comm) FAST_FUNC; #else diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 542211255..67c540abb 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -905,16 +905,8 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) # endif # if NUM_APPLETS > 0 -void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) +void FAST_FUNC show_usage_if_dash_dash_help(int applet_no, char **argv) { - int argc = string_array_len(argv); - - /* - * We do not use argv[0]: do not want to repeat massaging of - * "-/sbin/halt" -> "halt", for example. - */ - applet_name = name; - /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". * Thus for "test", we skip --help check. @@ -931,15 +923,32 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar && applet_no != APPLET_NO_false # endif ) { - if (argc == 2 && strcmp(argv[1], "--help") == 0) { + if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0) { /* Make "foo --help" exit with 0: */ xfunc_error_retval = 0; bb_show_usage(); } } +} + +void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) +{ + int argc; + + /* + * We do not use argv[0]: do not want to repeat massaging of + * "-/sbin/halt" -> "halt", for example. + */ + applet_name = name; + + show_usage_if_dash_dash_help(applet_no, argv); + if (ENABLE_FEATURE_SUID) check_suid(applet_no); + + argc = string_array_len(argv); xfunc_error_retval = applet_main[applet_no](argc, argv); + /* Note: applet_main() may also not return (die on a xfunc or such) */ xfunc_die(); } diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 65271e84f..a49fe8e01 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -109,8 +109,13 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) char *tmp_argv[argc+1]; memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); applet_name = tmp_argv[0]; + + /* longjmp's (instead of returning) if --help is seen */ + show_usage_if_dash_dash_help(applet_no, argv); + /* Finally we can call NOFORK applet's main() */ rc = applet_main[applet_no](argc, tmp_argv); + /* Important for shells: `which CMD` was failing */ fflush_all(); } else { -- cgit v1.2.3