]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
all: with multi-call binary, only process options for known names
authorPádraig Brady <P@draigBrady.com>
Thu, 15 Jan 2026 14:56:26 +0000 (14:56 +0000)
committerPádraig Brady <P@draigBrady.com>
Thu, 15 Jan 2026 15:54:29 +0000 (15:54 +0000)
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.

NEWS
src/coreutils.c
tests/misc/coreutils.sh

diff --git a/NEWS b/NEWS
index a2facb6361ac81585b17c2b6d75bf28f0c6f1f97..bd2be1baeefaba9ee9d45314f08bde76494a6fd3 100644 (file)
--- 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
index b13243cdc0c408d00182c8b5ecb9289c484ed756..a6497e20706b05d3a1c8709722c4bcd1bd970110 100644 (file)
@@ -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);
 }
index c2b4745affd648b8cdc35a5e7008511c50d63784..a554be090b7df275c3e93fab6cbd0b1d331790a4 100755 (executable)
 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