env: add -v/--debug option

Prints verbose information about each step:

  $ env -v -uFOO  -C /tmp BAR=BAZ date -u
  env: unset:    FOO
  env: setenv:   BAR=BAZ
  env: chdir:    '/tmp'
  env: executing: date
  env:    arg[0]= ‘date’
  env:    arg[1]= ‘-u’
  Sun Apr 22 08:52:30 UTC 2018

Inspired by FreeBSD's env(1).

* src/env.c (usage): Mention new option.
  (main): Print debug information if requested.
* NEWS: Mention new option.
* doc/coreutils.texi (env invocation): Mention -v/--debug.
This commit is contained in:
Assaf Gordon 2018-04-19 18:26:07 -06:00 committed by Pádraig Brady
parent 068b46e73b
commit a0118a71bb
3 changed files with 44 additions and 1 deletions

3
NEWS
View File

@ -50,6 +50,9 @@ GNU coreutils NEWS -*- outline -*-
** New features
env supports a new -v/--debug option to show verbose information about
each processing step.
md5sum accepts a new option: --zero (-z) to delimit the output lines with a
NUL instead of a newline character. This also disables file name escaping.
This also applies to sha*sum and b2sum.

View File

@ -17043,6 +17043,22 @@ chroot /chroot env --chdir=/srv true
env --chdir=/build FOO=bar timeout 5 true
@end example
@item -v
@itemx --debug
@opindex -v
@opindex --debug
Show verbose information for each processing step.
@example
$ env -v -uTERM A=B uname -s
unset: TERM
setenv: A=B
executing: uname
arg[0]= 'uname'
arg[1]= '-s'
Linux
@end example
@end table
@cindex exit status of @command{env}

View File

@ -38,12 +38,16 @@ static const char** usvars;
size_t usvars_alloc;
size_t usvars_used;
/* Annotate the output with extra info to aid the user. */
static bool dev_debug;
static struct option const longopts[] =
{
{"ignore-environment", no_argument, NULL, 'i'},
{"null", no_argument, NULL, '0'},
{"unset", required_argument, NULL, 'u'},
{"chdir", required_argument, NULL, 'C'},
{"debug", no_argument, NULL, 'v'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@ -72,6 +76,9 @@ Set each NAME to VALUE in the environment and run COMMAND.\n\
"), stdout);
fputs (_("\
-C, --chdir=DIR change working directory to DIR\n\
"), stdout);
fputs (_("\
-v, --debug print verbose information for each processing step\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@ -97,6 +104,8 @@ unset_envvars (void)
{
for (size_t i = 0; i < usvars_used; ++i)
{
devmsg ("unset: %s\n", usvars[i]);
if (unsetenv (usvars[i]))
die (EXIT_CANCELED, errno, _("cannot unset %s"),
quote (usvars[i]));
@ -125,7 +134,7 @@ main (int argc, char **argv)
initialize_exit_failure (EXIT_CANCELED);
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "+C:iu:0", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "+C:iu:v0", longopts, NULL)) != -1)
{
switch (optc)
{
@ -135,6 +144,9 @@ main (int argc, char **argv)
case 'u':
append_unset_var (optarg);
break;
case 'v':
dev_debug = true;
break;
case '0':
opt_nul_terminate_output = true;
break;
@ -156,6 +168,7 @@ main (int argc, char **argv)
if (ignore_environment)
{
devmsg ("cleaning environ\n");
static char *dummy_environ[] = { NULL };
environ = dummy_environ;
}
@ -165,6 +178,8 @@ main (int argc, char **argv)
char *eq;
while (optind < argc && (eq = strchr (argv[optind], '=')))
{
devmsg ("setenv: %s\n", argv[optind]);
if (putenv (argv[optind]))
{
*eq = '\0';
@ -199,11 +214,20 @@ main (int argc, char **argv)
if (newdir)
{
devmsg ("chdir: %s\n", quoteaf (newdir));
if (chdir (newdir) != 0)
die (EXIT_CANCELED, errno, _("cannot change directory to %s"),
quoteaf (newdir));
}
if (dev_debug)
{
devmsg ("executing: %s\n", argv[optind]);
for (int i=optind; i<argc; ++i)
devmsg (" arg[%d]= %s\n", i-optind, quote (argv[i]));
}
execvp (argv[optind], &argv[optind]);
int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;