From: Pádraig Brady
Date: Thu, 15 Jan 2026 14:56:26 +0000 (+0000) Subject: all: with multi-call binary, only process options for known names X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b32a0bbde15283bed37b2237d0436a163a57685;p=thirdparty%2Fcoreutils.git all: with multi-call binary, only process options for known names Setup $ ln -nsf src/coreutils foo Before $ ./foo; echo $? foo: unknown program ‘foo’ Try './foo --help' for more information. 1 ./foo --version; echo $? coreutils (GNU coreutils) 9.9.172-01993 0 After $ ./foo; echo $? coreutils: unknown program 'foo' 1 $ ./foo --version; echo $? coreutils: unknown program 'foo' 1 * src/coreutils.c (main): Don't process options if we don't know they're intended for the multi-call binary. Otherwise `foo --version` would return true, even though foo was symlinked to the multi-call binary, but not supported. * tests/misc/coreutils.sh: Add test cases. * NEWS: Mention the change in behavior. --- diff --git a/NEWS b/NEWS index a2facb6361..bd2be1baee 100644 --- a/NEWS +++ b/NEWS @@ -68,6 +68,10 @@ GNU coreutils NEWS -*- outline -*- 'timeout -v -s 0' now prints the signal number 0 instead of EXIT. + The multi-call binary now only processes --help or --version options + if it is installed with a name ending with "coreutils". This allows + for more consistent handling of these options with unsupported commands. + ** Improvements The multi-call binary built with configure --enable-single-binary diff --git a/src/coreutils.c b/src/coreutils.c index b13243cdc0..a6497e2070 100644 --- a/src/coreutils.c +++ b/src/coreutils.c @@ -148,9 +148,9 @@ main (int argc, char **argv) path/to/coreutils --coreutils-prog=someprog someprog ... The third argument is what the program will see as argv[0]. */ + size_t nskip = 0; if (argc >= 2) { - size_t nskip = 0; char *arg_name = nullptr; /* If calling coreutils directly, the "script" name isn't passed. @@ -174,13 +174,19 @@ main (int argc, char **argv) { argv[nskip] = arg_name; /* XXX: Discards any specified path. */ launch_program (prog_name, argc - nskip, argv + nskip); - error (EXIT_FAILURE, 0, _("unknown program %s"), - quote (prog_name)); } } - /* No known program was selected. From here on, we behave like any other - coreutils program. */ + /* Only process options if calling multi-call binary directly, + otherwise `foo --version` would succeed. */ + if (nskip || (prog_name && !str_endswith (prog_name, "coreutils"))) + { + fprintf (stderr, _("%s: unknown program %s\n"), + PROGRAM_NAME, quote (prog_name)); + exit (EXIT_FAILURE); + } + + /* From here on, we behave like any other coreutils program. */ initialize_main (&argc, &argv); set_program_name (argv[0]); setlocale (LC_ALL, ""); @@ -196,11 +202,5 @@ main (int argc, char **argv) case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); } - /* Only print the error message when no options have been passed - to coreutils. */ - if (optind == 1 && prog_name && !streq (prog_name, "coreutils")) - error (0, 0, _("unknown program %s"), - quote (prog_name)); - usage (EXIT_FAILURE); } diff --git a/tests/misc/coreutils.sh b/tests/misc/coreutils.sh index c2b4745aff..a554be090b 100755 --- a/tests/misc/coreutils.sh +++ b/tests/misc/coreutils.sh @@ -21,16 +21,23 @@ print_ver_ coreutils test -s "$abs_top_builddir/src/coreutils.h" \ - || skip_ "multicall binary is disabled" + || skip_ 'multicall binary is disabled' # Yes outputs all its params so is good to verify argv manipulations -echo 'y' > exp -coreutils --coreutils-prog=yes | head -n10 | uniq > out +echo 'y' > exp && +coreutils --coreutils-prog=yes | head -n10 | uniq > out || framework_failure_ compare exp out || fail=1 # Ensure if incorrect program passed, we diagnose -echo "coreutils: unknown program 'blah'" > exp -coreutils --coreutils-prog='blah' --help 2>err && fail=1 +echo "coreutils: unknown program 'blah'" > exp || framework_failure_ + +returns_ 1 coreutils --coreutils-prog='blah' --help 2>err || fail=1 +compare exp err || fail=1 + +ln -s $abs_top_builddir/src/coreutils$EXEEXT blah || framework_failure_ +returns_ 1 ./blah 2>err || fail=1 +compare exp err || fail=1 +returns_ 1 ./blah --version 2>err || fail=1 compare exp err || fail=1 Exit $fail