From nobody Tue Oct 15 06:30:25 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XSPNf1DTvz5YQYk; Tue, 15 Oct 2024 06:30:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XSPNf0W0Gz4tZ0; Tue, 15 Oct 2024 06:30:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1728973826; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=z1xIOFF4GH1zUqHVeP3TFbTj/3FseQJLqSVbUT++B4Y=; b=huSVTu6TG5VVET4OHPWtiUILcuKFqiUjAnKND7EL/POf1Tb+OpcHjmJN+FeAG2oD0HpylZ l/QDNGZwvmubjQ2FElSNmqB2PmqaOzwE+1VNFZY+Km7Ks80dPE3ekn9CSOqHFMzE1IpbQv IT4DnwlVTl/ZT4acqkSM0x6ZGIAXRAZuzTgNBczeKBRbEucw+dKxCBJ0+uYQLC+5F6DXRE qwd2j8KXZ3l8wsV3pDfM1xQXjYZb1Djvdl/k8LH3CrZ+QGQtKlcLf8mhgtjp7qG3hZIp4k Bhj/k0wXRFiXlan6QNCyLn6plCbSkG5DFidSvl65eQE8xNE4tUhZKfq12okcGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1728973826; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=z1xIOFF4GH1zUqHVeP3TFbTj/3FseQJLqSVbUT++B4Y=; b=FHy5mn9Qf8MrMuKBxvw9KjlfF4dkagTLMKdSRGaN+X4dabRnNHOA/eYzwtizY2GFrDYcJY iatRpBKQg6IW24VVyJ262Pp2TOYBu2Xl+ri5GUIC+JtzcsVLDJmxZXnDNS7bdOHbF6ZLey 31BFDgW5161qb87G5H7vlF5ZmQP/MeJYylC7UastXMDz9t+XWq9V8Z8CI24q3Pc2+aOFq/ g/yXCKVQo8h72vey4dmvvdl+THN8eiRnl7c+9iSmtwkojKDAH1BylYU6kbwqUvBB/XEVs/ YrkntDcgtm/XjSqKwZIIS+uc9QQgZ0KaLEW7DGUUgvDEsWrvILzkAxdgt6IQLQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1728973826; a=rsa-sha256; cv=none; b=hdhxHRJTJbfr6QUVeLUuAgyXB96TJWmpXAOc7iJV/nmg40Q0VCyhJqqULJshOJyejAlyim C8mDDr6ATPth0GcmFMC9CQYsvfSMBWorMoSbQrjIYCBfZtzDxXjZNHQIxiStAe5a22v3Qz u0ZswPcvXSE7DBeHcbCYtwjGhyClIgHdhoZTyj7G+3aDaR4ZtS2GermJEVNlOKgqXUQvQP JV9ECyTLs7sptQWNQxoeimyeZ9K+UGTHUSOAujTn3im84J4sSpegQvOtSN5Hm1aVXU82VG UgEhC5oIc+s0hX4X32xNnh7gEzdEI/xw87lyeJQLHcDGSC8rmk2KzWTKV4QLbg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XSPNd6Z41z19gG; Tue, 15 Oct 2024 06:30:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 49F6UP8r015961; Tue, 15 Oct 2024 06:30:25 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 49F6UP25015958; Tue, 15 Oct 2024 06:30:25 GMT (envelope-from git) Date: Tue, 15 Oct 2024 06:30:25 GMT Message-Id: <202410150630.49F6UP25015958@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 08e8554c4a39 - stable/14 - env: Add a handful of test cases. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 08e8554c4a39352da36f63794ef7d2b441a37238 Auto-Submitted: auto-generated The branch stable/14 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=08e8554c4a39352da36f63794ef7d2b441a37238 commit 08e8554c4a39352da36f63794ef7d2b441a37238 Author: Dag-Erling Smørgrav AuthorDate: 2024-10-07 21:00:17 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2024-10-15 05:25:15 +0000 env: Add a handful of test cases. MFC after: 3 days Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D46996 (cherry picked from commit 334af5e4131b21c658203635bf713d6a59846585) env: Improve documentation. * The `env` utility's inability to run a command whose name contains an equal sign is a feature, not a bug, so move that paragraph up from the BUGS section to the DESCRIPTION section. * Mention that this can be worked around by prefixing the command name with `command`, and add an example of this to the EXAMPLE section. * Add a test case which verifies that `env` does not run a command with an equal sign in its name even if it exists, and also demonstrates the workaround. MFC after: 3 days Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D46997 (cherry picked from commit a0dfb0668b45506de97beb4c7acbe3fd1ba69fc8) 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 (cherry picked from commit 6f6166e49c78f6460732c02bbbba6fcc218221cf) env: Check the status of stdout. MFC after: 3 days Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D47009 (cherry picked from commit c2d93a803acef634bd0eede6673aeea59e90c277) --- etc/mtree/BSD.tests.dist | 2 + usr.bin/env/Makefile | 4 ++ usr.bin/env/env.1 | 41 ++++++++--- usr.bin/env/env.c | 24 +++++-- usr.bin/env/tests/Makefile | 6 ++ usr.bin/env/tests/env_test.sh | 160 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 222 insertions(+), 15 deletions(-) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 95328d6d293f..a756236fd534 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1057,6 +1057,8 @@ .. du .. + env + .. factor .. file2c diff --git a/usr.bin/env/Makefile b/usr.bin/env/Makefile index af2e65dd5fc1..d7a34fce92aa 100644 --- a/usr.bin/env/Makefile +++ b/usr.bin/env/Makefile @@ -1,4 +1,5 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 +.include PACKAGE= runtime PROG= env @@ -6,4 +7,7 @@ SRCS= env.c envopts.c LIBADD= util +HAS_TESTS= +SUBDIR.${MK_TESTS}= tests + .include diff --git a/usr.bin/env/env.1 b/usr.bin/env/env.1 index 8aa78e110505..4badea716143 100644 --- a/usr.bin/env/env.1 +++ b/usr.bin/env/env.1 @@ -30,7 +30,7 @@ .\" From @(#)printenv.1 8.1 (Berkeley) 6/6/93 .\" From FreeBSD: src/usr.bin/printenv/printenv.1,v 1.17 2002/11/26 17:33:35 ru Exp .\" -.Dd March 3, 2021 +.Dd October 8, 2024 .Dt ENV 1 .Os .Sh NAME @@ -44,6 +44,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 @@ -81,6 +82,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 @@ -173,6 +180,19 @@ Both and .Ar utility may not be specified together. +.Pp +The +.Nm +utility does not handle values of +.Ar utility +which have an equals sign +.Pq Ql = +in their name, for obvious reasons. +This can easily be worked around by interposing the +.Xr command 1 +utility, which simply executes its arguments; see +.Sx EXAMPLES +below. .\" .Ss Details of -S (split-string) processing The processing of the @@ -471,6 +491,11 @@ and options: .Pp .Dl "#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl" +.Pp +To execute a utility with an equal sign in its name: +.Bd -literal -offset indent +env name=value ... command foo=bar arg ... +.Ed .Sh COMPATIBILITY The .Nm @@ -490,7 +515,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 @@ -513,15 +538,11 @@ and .Fl U options were added in .Fx 13.0 . -.Sh BUGS The -.Nm -utility does not handle values of -.Ar utility -which have an equals sign -.Pq Ql = -in their name, for obvious reasons. -.Pp +.Fl C +option was added in +.Fx 14.2 . +.Sh BUGS The .Nm utility does not take multibyte characters into account when diff --git a/usr.bin/env/env.c b/usr.bin/env/env.c index 784caa76063e..724a17d8be4f 100644 --- a/usr.bin/env/env.c +++ b/usr.bin/env/env.c @@ -72,7 +72,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; @@ -83,6 +83,7 @@ main(int argc, char **argv) int rtrn; altpath = NULL; + altwd = NULL; login_class = NULL; login_name = NULL; pw = NULL; @@ -90,7 +91,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': @@ -99,6 +100,9 @@ main(int argc, char **argv) case '0': term = '\0'; break; + case 'C': + altwd = optarg; + break; case 'U': login_as_user = true; /* FALLTHROUGH */ @@ -106,7 +110,7 @@ main(int argc, char **argv) login_name = optarg; break; case 'P': - altpath = strdup(optarg); + altpath = optarg; break; case 'S': /* @@ -199,6 +203,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) { @@ -212,9 +219,16 @@ 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); + if (fflush(stdout) != 0) + err(1, "stdout"); exit(0); } @@ -222,7 +236,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); } diff --git a/usr.bin/env/tests/Makefile b/usr.bin/env/tests/Makefile new file mode 100644 index 000000000000..3d2f77b34b67 --- /dev/null +++ b/usr.bin/env/tests/Makefile @@ -0,0 +1,6 @@ +PACKAGE= tests + +ATF_TESTS_SH= env_test +BINDIR= ${TESTSDIR} + +.include diff --git a/usr.bin/env/tests/env_test.sh b/usr.bin/env/tests/env_test.sh new file mode 100644 index 000000000000..2dc8f1a4c911 --- /dev/null +++ b/usr.bin/env/tests/env_test.sh @@ -0,0 +1,160 @@ +# +# Copyright (c) 2024 Klara, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause +# + +magic_words="Squeamish $$ Ossifrage" + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Basic test case" +} +basic_body() +{ + atf_check -o match:"^magic_words=${magic_words}\$" \ + env magic_words="${magic_words}" + export MAGIC_WORDS="${magic_words}" + atf_check -o match:"^MAGIC_WORDS=${magic_words}\$" \ + env + unset MAGIC_WORDS +} + +atf_test_case unset +unset_head() +{ + atf_set "descr" "Unset a variable" +} +unset_body() +{ + export MAGIC_WORDS="${magic_words}" + atf_check -o not-match:"^MAGIC_WORDS=" \ + env -u MAGIC_WORDS + unset MAGIC_WORDS +} + +atf_test_case empty +empty_head() +{ + atf_set "descr" "Empty environment" +} +empty_body() +{ + atf_check env -i +} + +atf_test_case true +true_head() +{ + atf_set "descr" "Run true" +} +true_body() +{ + atf_check env true +} + +atf_test_case false +false_head() +{ + atf_set "descr" "Run false" +} +false_body() +{ + atf_check -s exit:1 env false +} + +atf_test_case false +false_head() +{ + atf_set "descr" "Run false" +} +false_body() +{ + atf_check -s exit:1 env false +} + +atf_test_case altpath +altpath_head() +{ + atf_set "descr" "Use alternate path" +} +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" \ + env -P "${PWD}" magic_words +} + +atf_test_case equal +equal_head() +{ + atf_set "descr" "Command name contains equal sign" +} +equal_body() +{ + echo "echo ${magic_words}" >"magic=words" + chmod 0755 "magic=words" + atf_check -o match:"^${PWD}/magic=words$" \ + env "${PWD}/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" + atf_check -o inline:"${magic_words}\n" \ + 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_test_case stdout +stdout_head() +{ + atf_set descr "Failure to write to stdout" +} +stdout_body() +{ + ( + trap "" PIPE + env 2>stderr + echo $? >result + ) | true + atf_check -o inline:"1\n" cat result + atf_check -o match:"stdout" cat stderr +} + +atf_init_test_cases() +{ + atf_add_test_case basic + atf_add_test_case unset + atf_add_test_case empty + atf_add_test_case true + atf_add_test_case false + atf_add_test_case altpath + atf_add_test_case equal + atf_add_test_case chdir + atf_add_test_case stdout +}