On 13/03/2024 10:19, Matheus Afonso Martins Moreira wrote:
About a year ago, I posted an env feature request on this list:
the ability to set the value of argv[0].

https://lists.gnu.org/archive/html/coreutils/2023-03/msg00002.html

I also sent a patch:

https://lists.gnu.org/archive/html/coreutils/2023-03/msg00003.html

After some discussion, I was informed it was under consideration:

https://lists.gnu.org/archive/html/coreutils/2023-03/msg00012.html

We're still considering and will adjust as needed.

I waited a while and eventually sent an email about it:

https://lists.gnu.org/archive/html/coreutils/2023-08/msg00059.html

The maintainer noted that they expected this feature to be included
in the next release which would be focused on features:

https://lists.gnu.org/archive/html/coreutils/2023-08/msg00060.html

The next release will focus on new features, and this
will be considered. I expect this feature will be included.

Since then I've been tracking commits to the coreutils master branch
but it appears the feature has not landed yet.

What happened? Was it rejected?


Thanks for your patience.
I've attached an implementation for --argv0
which I intend to apply for the impending release.
Note this can accept empty and NULL values,
and so now gives env full control of the args it passes on.

thanks,
Pádraig.
From a2f4ef43c67450d13a12bc63c72f16c690670dfa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Thu, 2 Mar 2023 11:56:18 -0300
Subject: [PATCH] env: add --argv0 to set the first argument passed to exec

Using the shell's exec -a feature can be awkward
so add support for setting argv0 to arbitrary values.
This gives env full control over the arguments it passes.

* src/env.c: Accept --argv0 and set argv[0] appropriately.
* tests/env/env.sh: Add test cases.
* doc/coreutils.texi (env invocation): Describe --argv0.
* NEWS: Mention the new feature.
---
 NEWS               |  3 +++
 doc/coreutils.texi |  8 ++++++++
 src/env.c          | 31 +++++++++++++++++++++++++++----
 tests/env/env.sh   | 26 ++++++++++++++++++++++++++
 4 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/NEWS b/NEWS
index b3004273b..839582c16 100644
--- a/NEWS
+++ b/NEWS
@@ -92,6 +92,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   and the command exits with failure status if existing files.
   The -n,--no-clobber option is best avoided due to platform differences.
 
+  env now accepts the --argv0 option to override the zeroth argument
+  of the command being executed.
+
   od now supports printing IEEE half precision floating point with -t fH,
   or brain 16 bit floating point with -t fB, where supported by the compiler.
 
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ec15a467f..766925623 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -17927,6 +17927,14 @@ Options must precede operands.
 
 @optNull
 
+@item --argv0[=@var{arg}]
+@opindex --argv0
+By default @var{command} is used as the zeroth argument passed to
+the command being executed, which can be overridden with this option.
+@var{arg} is optional, and set to the NULL is not specified.
+For example, @samp{--argv0=} would pass the empty string,
+while @samp{--argv0} would pass a NULL pointer.
+
 @item -u @var{name}
 @itemx --unset=@var{name}
 @opindex -u
diff --git a/src/env.c b/src/env.c
index ed6628f8f..dc08b2dba 100644
--- a/src/env.c
+++ b/src/env.c
@@ -79,7 +79,8 @@ static char const shortopts[] = "+C:iS:u:v0" C_ISSPACE_CHARS;
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
 {
-  DEFAULT_SIGNAL_OPTION = CHAR_MAX + 1,
+  ARGV0_OPTION = CHAR_MAX + 1,
+  DEFAULT_SIGNAL_OPTION,
   IGNORE_SIGNAL_OPTION,
   BLOCK_SIGNAL_OPTION,
   LIST_SIGNAL_HANDLING_OPTION,
@@ -87,6 +88,7 @@ enum
 
 static struct option const longopts[] =
 {
+  {"argv0", optional_argument, nullptr, ARGV0_OPTION},
   {"ignore-environment", no_argument, nullptr, 'i'},
   {"null", no_argument, nullptr, '0'},
   {"unset", required_argument, nullptr, 'u'},
@@ -119,6 +121,9 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
       emit_mandatory_arg_note ();
 
       fputs (_("\
+      --argv0[=ARG]    pass ARG as the zeroth argument of COMMAND\n\
+"), stdout);
+      fputs (_("\
   -i, --ignore-environment  start with an empty environment\n\
   -0, --null           end each output line with NUL, not newline\n\
   -u, --unset=NAME     remove variable from the environment\n\
@@ -759,6 +764,7 @@ main (int argc, char **argv)
   bool ignore_environment = false;
   bool opt_nul_terminate_output = false;
   char const *newdir = nullptr;
+  char *argv0 = *argv;  /* Initialize to a distinct but unused value.  */
 
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -775,6 +781,9 @@ main (int argc, char **argv)
     {
       switch (optc)
         {
+        case ARGV0_OPTION:
+          argv0 = optarg;
+          break;
         case 'i':
           ignore_environment = true;
           break;
@@ -865,6 +874,12 @@ main (int argc, char **argv)
       usage (EXIT_CANCELED);
     }
 
+  if (argv0 != *argv && ! program_specified)
+    {
+      error (0, 0, _("must specify command with --argv0 (-a)"));
+      usage (EXIT_CANCELED);
+    }
+
   if (! program_specified)
     {
       /* Print the environment and exit.  */
@@ -890,14 +905,22 @@ main (int argc, char **argv)
                quoteaf (newdir));
     }
 
+  char *program = argv[optind];
+  if (argv0 != *argv)
+    {
+      devmsg ("argv0:     %s\n", argv0 ? quoteaf (argv0) : "(null)");
+      argv[optind] = argv0;
+    }
+
   if (dev_debug)
     {
-      devmsg ("executing: %s\n", argv[optind]);
+      devmsg ("executing: %s\n", program);
       for (int i=optind; i<argc; ++i)
-        devmsg ("   arg[%d]= %s\n", i-optind, quote (argv[i]));
+        devmsg ("   arg[%d]= %s\n", i-optind,
+                argv[i] ? quote (argv[i]) : "(null)");
     }
 
-  execvp (argv[optind], &argv[optind]);
+  execvp (program, &argv[optind]);
 
   int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
   error (0, errno, "%s", quote (argv[optind]));
diff --git a/tests/env/env.sh b/tests/env/env.sh
index 1a4b1a53f..8b4689414 100755
--- a/tests/env/env.sh
+++ b/tests/env/env.sh
@@ -163,4 +163,30 @@ exp=$(cd empty && env pwd) || framework_failure_
 got=$(env --chdir=empty pwd) || fail=1
 test "$exp" = "$got" || fail=1
 
+# Verify argv0 overriding
+# normal string
+env -v --argv0=argv0 true 2>err || fail=1
+cat <<EOF >err_exp || framework_failure_
+argv0:     'argv0'
+executing: true
+   arg[0]= 'argv0'
+EOF
+compare err_exp err || fail=1
+# empty string
+env -v --argv0= true 2>err || fail=1
+cat <<EOF >err_exp || framework_failure_
+argv0:     ''
+executing: true
+   arg[0]= ''
+EOF
+compare err_exp err || fail=1
+# NULL string
+env -v --argv0 true 2>err || fail=1
+cat <<EOF >err_exp || framework_failure_
+argv0:     (null)
+executing: true
+   arg[0]= (null)
+EOF
+compare err_exp err || fail=1
+
 Exit $fail
-- 
2.43.0

Reply via email to