On 28/08/17 16:08, Bernhard Voelker wrote: > On 08/27/2017 09:23 AM, Colin Watson wrote: >> From 0a74257b9fb7e02587b6c5553d8bc1b536249a7e Mon Sep 17 00:00:00 2001 >> From: Colin Watson <cjwat...@debian.org> >> Date: Sun, 27 Aug 2017 08:16:21 +0100 >> Subject: [PATCH] env: add --chdir option >> >> This is useful when chaining with other commands that run commands in a >> different context. >> >> * NEWS (New features): Document the new option. >> * doc/coreutils.texi (env invocation): Likewise. >> * src/env.c (usage): Likewise. >> (main): Implement the new option. >> * tests/misc/env.sh: Test the new option. >> --- >> NEWS | 3 +++ >> doc/coreutils.texi | 17 +++++++++++++++++ >> src/env.c | 20 ++++++++++++++++++++ >> tests/misc/env.sh | 10 +++++++++- >> 4 files changed, 49 insertions(+), 1 deletion(-) >> >> diff --git a/NEWS b/NEWS >> index d37195e..60d5ca5 100644 >> --- a/NEWS >> +++ b/NEWS >> @@ -86,6 +86,9 @@ GNU coreutils NEWS -*- >> outline -*- >> >> expr supports multibyte strings for all string operations. >> >> + env now has a --chdir option to change to a new working directory before >> + executing the subsidiary program. >> + > > To me (as non-native), "new working directory" might sound like the > directory may be created at the same time, doesn't it? > Maybe > s/to change to a new working directory/to change the working directory/ > ?
ack >> ** Improvements >> >> mv --verbose now distinguishes rename and copy operations. >> diff --git a/doc/coreutils.texi b/doc/coreutils.texi >> index 8f1cb4c..f127517 100644 >> --- a/doc/coreutils.texi >> +++ b/doc/coreutils.texi >> @@ -16909,6 +16909,23 @@ environment. >> @opindex --ignore-environment >> Start with an empty environment, ignoring the inherited environment. >> >> +@item --chdir=@var{dir} >> +@opindex --chdir >> +Change the working directory to @var{dir} before invoking @var{command}. >> +This differs from the shell built-in @command{cd} in that it starts >> +@var{command} as a subprocess rather than altering the shell's own working >> +directory; this allows it to be chained with other commands that run >> commands >> +in a different context. For example: >> + >> +@example >> +# Run 'true' with /chroot as its root directory and /srv as its working >> +# directory. >> +chroot /chroot env --chdir=/srv true >> +# Run 'true' with /build as its working directory, FOO=bar in its >> +# environment, and a time limit of five seconds. >> +env --chdir=/build FOO=bar timeout 5 true >> +@end example >> + >> @end table >> >> @cindex exit status of @command{env} >> diff --git a/src/env.c b/src/env.c >> index 63d5c2c..291fbb4 100644 >> --- a/src/env.c >> +++ b/src/env.c >> @@ -33,11 +33,19 @@ >> proper_name ("Richard Mlynarik"), \ >> proper_name ("David MacKenzie") >> >> +/* For long options that have no equivalent short option, use a >> + non-character as a pseudo short option, starting with CHAR_MAX + 1. */ >> +enum >> +{ >> + CHDIR = CHAR_MAX + 1 >> +}; >> + >> 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, CHDIR}, >> {GETOPT_HELP_OPTION_DECL}, >> {GETOPT_VERSION_OPTION_DECL}, >> {NULL, 0, NULL, 0} >> @@ -63,6 +71,7 @@ Set each NAME to VALUE in the environment and run >> COMMAND.\n\ >> -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\ >> + --chdir=DIR change working directory to DIR\n\ >> "), stdout); >> fputs (HELP_OPTION_DESCRIPTION, stdout); >> fputs (VERSION_OPTION_DESCRIPTION, stdout); >> @@ -81,6 +90,7 @@ main (int argc, char **argv) >> int optc; >> bool ignore_environment = false; >> bool opt_nul_terminate_output = false; >> + char const *newdir = NULL; >> >> initialize_main (&argc, &argv); >> set_program_name (argv[0]); >> @@ -103,6 +113,9 @@ main (int argc, char **argv) >> case '0': >> opt_nul_terminate_output = true; >> break; >> + case CHDIR: >> + newdir = optarg; >> + break; > > Please use tab-free indentation as throughout the whole coreutils > sources. ack (make syntax-check catches this) >> case_GETOPT_HELP_CHAR; >> case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); >> default: >> @@ -154,6 +167,13 @@ main (int argc, char **argv) >> usage (EXIT_CANCELED); >> } >> >> + if (newdir) >> + { >> + if (chdir (newdir) != 0) >> + die (EXIT_CANCELED, errno, _("cannot change directory to %s"), >> + quoteaf (newdir)); >> + } >> + > > Likewise. > >> execvp (argv[optind], &argv[optind]); >> >> int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; >> diff --git a/tests/misc/env.sh b/tests/misc/env.sh >> index f2f6ba8..c409630 100755 >> --- a/tests/misc/env.sh >> +++ b/tests/misc/env.sh >> @@ -18,7 +18,7 @@ >> >> >> . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src >> -print_ver_ env >> +print_ver_ env pwd >> >> # A simple shebang program to call "echo" from symlinks like "./-u" or >> "./--". >> echo "#!$abs_top_builddir/src/echo simple_echo" > simple_echo \ >> @@ -150,4 +150,12 @@ test "x$(sh -c '\c=d echo fail')" = xpass && #dash >> 0.5.4 fails so check first >> returns_ 125 env -u a=b true || fail=1 >> returns_ 125 env -u '' true || fail=1 >> >> +# Verify changing directory. >> +mkdir empty || framework_failure_ >> +returns_ 125 env --chdir=empty/nonexistent true || fail=1 >> +curdir=$(env pwd) || fail=1 >> +test "$curdir" = "$(pwd)" || fail=1 > > The above does not run CU's version of pwd, but instead > that of the shell. The test therefore fails when "pwd -L" > != "pwd -P" (and the implementation of coreutils and that > of the shell differs). > >> +curdir=$(env --chdir=empty pwd) || fail=1 >> +test "$curdir" = "$(cd empty && pwd)" || fail=1 >> + >> Exit $fail >> -- > > I therefore propose to squash in the following change: > > diff --git a/tests/misc/env.sh b/tests/misc/env.sh > index c409630..7c864cd 100755 > --- a/tests/misc/env.sh > +++ b/tests/misc/env.sh > @@ -153,9 +153,8 @@ returns_ 125 env -u '' true || fail=1 > # Verify changing directory. > mkdir empty || framework_failure_ > returns_ 125 env --chdir=empty/nonexistent true || fail=1 > -curdir=$(env pwd) || fail=1 > -test "$curdir" = "$(pwd)" || fail=1 > -curdir=$(env --chdir=empty pwd) || fail=1 > -test "$curdir" = "$(cd empty && pwd)" || fail=1 > +exp=$(cd empty && env pwd) || framework_failure_ > +got=$(env --chdir=empty pwd) || fail=1 This is missing the `test`, but I'll change as you intended. thanks! Pádraig