env: Add an option to change the directory.

This mirrors the equivalent option in GNU coreutils env, but does not
add support for long options.

MFC after:	3 days
Relnotes:	yes
Sponsored by:	Klara, Inc.
Reviewed by:	0mp, bcr
Differential Revision:	https://reviews.freebsd.org/D47008
This commit is contained in:
Dag-Erling Smørgrav 2024-10-08 19:01:32 +02:00
parent e3ebc5f534
commit 6f6166e49c
3 changed files with 54 additions and 8 deletions

15
usr.bin/env/env.1 vendored
View file

@ -28,7 +28,7 @@
.\" SUCH DAMAGE.
.\" From FreeBSD: src/usr.bin/printenv/printenv.1,v 1.17 2002/11/26 17:33:35 ru Exp
.\"
.Dd October 7, 2024
.Dd October 8, 2024
.Dt ENV 1
.Os
.Sh NAME
@ -42,6 +42,7 @@
.Op Ar name Ns = Ns Ar value ...
.Nm
.Op Fl iv
.Op Fl C Ar altwd
.Op Fl L Ns | Ns Fl U Ar user Ns Op / Ns Ar class
.Op Fl P Ar altpath
.Op Fl S Ar string
@ -79,6 +80,12 @@ The environment inherited
by
.Nm
is ignored completely.
.\" -C
.It Fl C Ar altwd
Change to the specified alternate working directory before executing
the specified
.Ar utility
program.
.\" -L | -U
.It Fl L | Fl U Ar user Ns Op / Ns Ar class
Add the environment variable definitions from
@ -506,7 +513,7 @@ The
utility conforms to
.St -p1003.1-2001 .
The
.Fl 0 , L , P , S , U , u
.Fl 0 , C , L , P , S , U , u
and
.Fl v
options are non-standard extensions supported by
@ -529,6 +536,10 @@ and
.Fl U
options were added in
.Fx 13.0 .
The
.Fl C
option was added in
.Fx 14.2 .
.Sh BUGS
The
.Nm

22
usr.bin/env/env.c vendored
View file

@ -59,7 +59,7 @@ static void usage(void) __dead2;
int
main(int argc, char **argv)
{
char *altpath, **ep, *p, **parg, term;
char *altpath, *altwd, **ep, *p, **parg, term;
char *cleanenv[1];
char *login_class, *login_name;
struct passwd *pw;
@ -70,6 +70,7 @@ main(int argc, char **argv)
int rtrn;
altpath = NULL;
altwd = NULL;
login_class = NULL;
login_name = NULL;
pw = NULL;
@ -77,7 +78,7 @@ main(int argc, char **argv)
login_as_user = false;
want_clear = 0;
term = '\n';
while ((ch = getopt(argc, argv, "-0iL:P:S:U:u:v")) != -1)
while ((ch = getopt(argc, argv, "-0C:iL:P:S:U:u:v")) != -1)
switch(ch) {
case '-':
case 'i':
@ -86,6 +87,9 @@ main(int argc, char **argv)
case '0':
term = '\0';
break;
case 'C':
altwd = optarg;
break;
case 'U':
login_as_user = true;
/* FALLTHROUGH */
@ -93,7 +97,7 @@ main(int argc, char **argv)
login_name = optarg;
break;
case 'P':
altpath = strdup(optarg);
altpath = optarg;
break;
case 'S':
/*
@ -186,6 +190,9 @@ main(int argc, char **argv)
if (*argv) {
if (term == '\0')
errx(EXIT_CANCELED, "cannot specify command with -0");
if (altwd && chdir(altwd) != 0)
err(EXIT_CANCELED, "cannot change directory to '%s'",
altwd);
if (altpath)
search_paths(altpath, argv);
if (env_verbosity) {
@ -199,6 +206,11 @@ main(int argc, char **argv)
execvp(*argv, argv);
err(errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE,
"%s", *argv);
} else {
if (altwd)
errx(EXIT_CANCELED, "must specify command with -C");
if (altpath)
errx(EXIT_CANCELED, "must specify command with -P");
}
for (ep = environ; *ep; ep++)
(void)printf("%s%c", *ep, term);
@ -209,7 +221,7 @@ static void
usage(void)
{
(void)fprintf(stderr,
"usage: env [-0iv] [-L|-U user[/class]] [-P utilpath] [-S string] [-u name]\n"
" [name=value ...] [utility [argument ...]]\n");
"usage: env [-0iv] [-C workdir] [-L|-U user[/class]] [-P utilpath] [-S string]\n"
" [-u name] [name=value ...] [utility [argument ...]]\n");
exit(1);
}

View file

@ -83,6 +83,8 @@ altpath_body()
{
echo "echo ${magic_words}" >magic_words
chmod 0755 magic_words
atf_check -s exit:125 -e match:"must specify command" \
env -P "${PWD}"
atf_check -s exit:127 -e match:"No such file" \
env magic_words
atf_check -o inline:"${magic_words}\n" \
@ -100,7 +102,7 @@ equal_body()
chmod 0755 "magic=words"
atf_check -o match:"^${PWD}/magic=words$" \
env "${PWD}/magic=words"
atf_check -o match:"^magic=words$" \
atf_check -s exit:125 -e match:"must specify command" \
env -P "${PATH}:${PWD}" "magic=words"
atf_check -o inline:"${magic_words}\n" \
env command "${PWD}/magic=words"
@ -108,6 +110,26 @@ equal_body()
env PATH="${PATH}:${PWD}" command "magic=words"
}
atf_test_case chdir
chdir_head()
{
atf_set "descr" "Change working directory"
}
chdir_body()
{
local subdir="dir.$$"
atf_check -o inline:"${PWD}\n" \
env pwd
atf_check -s exit:125 -e match:"must specify command" \
env -C "${subdir}"
atf_check -s exit:125 \
-e match:"cannot change directory to '${subdir}':" \
env -C "${subdir}" pwd
atf_check mkdir "${subdir}"
atf_check -o inline:"${PWD}/${subdir}\n" \
env -C "${subdir}" pwd
}
atf_init_test_cases()
{
atf_add_test_case basic
@ -117,4 +139,5 @@ atf_init_test_cases()
atf_add_test_case false
atf_add_test_case altpath
atf_add_test_case equal
atf_add_test_case chdir
}