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; ierr || fail=1 +cat <err_exp || framework_failure_ +argv0: '$arg' +executing: true + arg[0]= '$arg' +EOF +done + Exit $fail -- 2.44.0