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.
---
 src/coreutils.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/coreutils.c b/src/coreutils.c
index b13243cdc..a6497e207 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);
 }
-- 
2.52.0


Reply via email to