diff --git a/usr.bin/env/env.1 b/usr.bin/env/env.1 --- a/usr.bin/env/env.1 +++ b/usr.bin/env/env.1 @@ -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 @@ 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 diff --git a/usr.bin/env/env.c b/usr.bin/env/env.c --- a/usr.bin/env/env.c +++ b/usr.bin/env/env.c @@ -59,7 +59,7 @@ 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 @@ int rtrn; altpath = NULL; + altwd = NULL; login_class = NULL; login_name = NULL; pw = NULL; @@ -77,7 +78,7 @@ 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 @@ case '0': term = '\0'; break; + case 'C': + altwd = optarg; + break; case 'U': login_as_user = true; /* FALLTHROUGH */ @@ -93,7 +97,7 @@ login_name = optarg; break; case 'P': - altpath = strdup(optarg); + altpath = optarg; break; case 'S': /* @@ -186,6 +190,9 @@ 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 @@ 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 @@ 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); } diff --git a/usr.bin/env/tests/env_test.sh b/usr.bin/env/tests/env_test.sh --- a/usr.bin/env/tests/env_test.sh +++ b/usr.bin/env/tests/env_test.sh @@ -83,6 +83,8 @@ { 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 @@ 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 @@ 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_add_test_case false atf_add_test_case altpath atf_add_test_case equal + atf_add_test_case chdir }