From 38653861b6e353e9f306d92e2e96179040e5b9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?=
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 | 7 +++++++
src/env.c | 31 ++++++++++++++++++++++++++-----
tests/env/env.sh | 10 ++++++++++
4 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/NEWS b/NEWS
index cb4762188..4110cafaf 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.
+
mv now accepts an --exchange option, which causes the source and
destination to be exchanged. It should be combined with
--no-target-directory (-T) if the destination is a directory.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index e36269588..5f7646039 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -17948,6 +17948,13 @@ Options must precede operands.
@optNull
+@item -a @var{arg}
+@itemx --argv0=@var{arg}
+@opindex -a
+@opindex --argv0
+Override the the zeroth argument passed to the command being executed.
+Without this option a default value of @var{command} is used.
+
@item -u @var{name}
@itemx --unset=@var{name}
@opindex -u
diff --git a/src/env.c b/src/env.c
index ed6628f8f..af876fa08 100644
--- a/src/env.c
+++ b/src/env.c
@@ -73,7 +73,7 @@ static bool report_signal_handling;
/* The isspace characters in the C locale. */
#define C_ISSPACE_CHARS " \t\n\v\f\r"
-static char const shortopts[] = "+C:iS:u:v0" C_ISSPACE_CHARS;
+static char const shortopts[] = "+a:C:iS:u:v0" C_ISSPACE_CHARS;
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
@@ -87,6 +87,7 @@ enum
static struct option const longopts[] =
{
+ {"argv0", required_argument, nullptr, 'a'},
{"ignore-environment", no_argument, nullptr, 'i'},
{"null", no_argument, nullptr, '0'},
{"unset", required_argument, nullptr, 'u'},
@@ -118,6 +119,9 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
emit_mandatory_arg_note ();
+ fputs (_("\
+ -a, --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\
@@ -759,6 +763,7 @@ main (int argc, char **argv)
bool ignore_environment = false;
bool opt_nul_terminate_output = false;
char const *newdir = nullptr;
+ char *argv0 = nullptr;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -775,6 +780,9 @@ main (int argc, char **argv)
{
switch (optc)
{
+ case 'a':
+ argv0 = optarg;
+ break;
case 'i':
ignore_environment = true;
break;
@@ -865,6 +873,12 @@ main (int argc, char **argv)
usage (EXIT_CANCELED);
}
+ if (argv0 && ! program_specified)
+ {
+ error (0, 0, _("must specify command with --argv0 (-a)"));
+ usage (EXIT_CANCELED);
+ }
+
if (! program_specified)
{
/* Print the environment and exit. */
@@ -890,19 +904,26 @@ main (int argc, char **argv)
quoteaf (newdir));
}
+ char *program = argv[optind];
+ if (argv0)
+ {
+ devmsg ("argv0: %s\n", quoteaf (argv0));
+ argv[optind] = argv0;
+ }
+
if (dev_debug)
{
- devmsg ("executing: %s\n", argv[optind]);
+ devmsg ("executing: %s\n", program);
for (int i=optind; i