Pádraig Brady <[email protected]> writes: >>> user_color=$(run0 --user="$user" printenv user_color) >>> >>> E.g. if $user_color contained ANSI escapes we'd want them unquoted. >>> Note the trailing newline would be auto stripped in the above, >>> allowing such usage. >> I think I agree. It feels a little weird to behave differently based >> on >> the number of arguments, but I think that case warrants it. > > It would be a bit more consistent to key on whether args were specified at > all. > So 1 or more args would only quote if connected to a tty. > >> I've attached an incomplete patch to do that. I'll probably adjust NEWS >> and the documentation a bit. > > NEWS is fine I think. > Details on this are best restricted to the texinfo description. > >> One thing I'm unsure about is whether a test for tty output should be >> added to the same test or in misc/tty-quoting.sh. It seems like the ones >> there are tailored to a single argument, where we should test both >> single argument and multiple arguments in this case, I think. I don't >> want that look to be *too* full of edge cases such that it gets >> difficult to understand. WDYT? > It would be good to add the arg specified case to tty-quoting.sha > to document the commands that are tty sensitive. > A single arg case is fine here. > > The existing cases are fine in misc/printenv.sh, > but tweaked to the adjusted non quoting.
How does the attached patch look? I'm sort of leaning towards it being worth expanding on the rationale in the manual, but I feel 'run0' is a little too Linux specific. I couldn't think of any better examples, though, so I left it out for now. AFAIK, sudo only allows you to preserve the entire environment or specific variables. I.e., there is no way to set a variable to a given value. Collin
>From 20c3044b68e9494e1ad9c6332fb1e48dbdf7d62b Mon Sep 17 00:00:00 2001 Message-ID: <20c3044b68e9494e1ad9c6332fb1e48dbdf7d62b.1788142310.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Sat, 29 Aug 2026 12:49:06 -0700 Subject: [PATCH v2] printenv: don't quote output when given arguments and redirected * src/printenv.c (main): Make sure quoting is disabled when we have arguments and standard output is not a terminal. * tests/misc/printenv.sh: Adjust single argument test cases. Add multiple argument test cases. * tests/misc/tty-quoting.sh: Add test cases to check if isatty is used. * doc/coreutils.texi (printenvAlwaysQuoted): Remove macro. (printenv invocation): Describe the adjusted quoting behavior. (env invocation): Move the text from printenvAlwaysQuoted here since it is no longer used for 'printenv'. --- doc/coreutils.texi | 21 +++++++++++++-------- src/printenv.c | 5 +++-- tests/misc/printenv.sh | 18 +++++++++++++----- tests/misc/tty-quoting.sh | 14 ++++++++++---- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 9fe4ba032..46854db4a 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -15519,14 +15519,15 @@ @node printenv invocation @end table -@macro printenvAlwaysQuoted -The printed environment variables and their values are quoted using the -@samp{shell-escape} style. The environment variable -@env{QUOTING_STYLE} specifies the quoting style. Valid quoting styles -are: +If no @var{variable}s are specified, @command{printenv} quotes +environment variables and their values using the @samp{shell-escape} +style. If @var{variable}s are specified, @command{printenv} only quotes +their values using the @samp{shell-escape} style if standard output is a +terminal. + +The environment variable @env{QUOTING_STYLE} +specifies the quoting style. Valid quoting styles are: @quotingStyles -@end macro -@printenvAlwaysQuoted @cindex exit status of @command{printenv} Exit status: @@ -17496,7 +17497,11 @@ @node env invocation specifications, the resulting environment is printed. This is like specifying the @command{printenv} program. -@printenvAlwaysQuoted +The printed environment variables and their values are quoted using the +@samp{shell-escape} style. The environment variable +@env{QUOTING_STYLE} specifies the quoting style. Valid quoting styles +are: +@quotingStyles For some examples, suppose the environment passed to @command{env} contains @samp{LOGNAME=rms}, @samp{EDITOR=emacs}, and diff --git a/src/printenv.c b/src/printenv.c index 540f56334..dba87f373 100644 --- a/src/printenv.c +++ b/src/printenv.c @@ -111,8 +111,9 @@ main (int argc, char **argv) } bool quote_output = false; + idx_t const n_args = argc - optind; - if (!opt_nul_terminate_output) + if (!opt_nul_terminate_output && (n_args <= 0 || isatty (STDOUT_FILENO))) { int qs = getenv_quoting_style (); if (qs < 0) @@ -130,7 +131,7 @@ main (int argc, char **argv) if (opt_nul_terminate_output) xset_binary_mode (STDOUT_FILENO, O_BINARY); - if (optind >= argc) + if (n_args <= 0) { for (char **env = environ; *env != NULL; ++env) print_envvar (*env, terminator, quote_output); diff --git a/tests/misc/printenv.sh b/tests/misc/printenv.sh index 8ec228a6a..a6eab09f6 100755 --- a/tests/misc/printenv.sh +++ b/tests/misc/printenv.sh @@ -84,17 +84,21 @@ compare /dev/null out || fail=1 cat <<\EOF >exp-noargs-literal || framework_failure_ a b=c d EOF +cat <<\EOF >exp-arg-literal || framework_failure_ +c d +EOF cat <<\EOF >exp-args-literal || framework_failure_ c d +c d EOF cat <<\EOF >exp-noargs-shell || framework_failure_ 'a b'='c d' EOF -cat <<\EOF >exp-args-shell || framework_failure_ -'c d' -EOF -tr "'" '"' <exp-noargs-shell >exp-noargs-c || framework_failure_ -tr "'" '"' <exp-args-shell >exp-args-c || framework_failure_ +cp exp-arg-literal exp-arg-shell && +cp exp-args-literal exp-args-shell || framework_failure_ +for t in noargs arg args; do + tr "'" '"' <exp-$t-shell >exp-$t-c || framework_failure_ +done for qs in literal shell c; do env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \ printenv >out-t 2>err || fail=1 @@ -104,6 +108,10 @@ for qs in literal shell c; do compare /dev/null err || fail=1 env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \ printenv 'a b' >out 2>err || fail=1 + compare exp-arg-$qs out || fail=1 + compare /dev/null err || fail=1 + env -i PATH="$PATH" QUOTING_STYLE=$qs 'a b'='c d' \ + printenv 'a b' 'a b' >out 2>err || fail=1 compare exp-args-$qs out || fail=1 compare /dev/null err || fail=1 done diff --git a/tests/misc/tty-quoting.sh b/tests/misc/tty-quoting.sh index a0dc1d4b8..833dfaedb 100755 --- a/tests/misc/tty-quoting.sh +++ b/tests/misc/tty-quoting.sh @@ -44,16 +44,22 @@ run_tty_ env test -t 1 || run_tty_ env printf foo >printf.t && skip_ 'libc buffering induced a tty probe' -for cmd in basename du dirname 'ls -w0' readlink 'realpath --relative-to=.'; do +for cmd in basename du dirname 'ls -w0' readlink 'realpath --relative-to=.' \ + printenv; do test "$cmd" = 'du' && field=2 || field=1 - test "$cmd" = 'dirname' && file='f oo/.' || file='f oo' + case "$cmd" in + dirname) file='f oo/.' ;; + printenv) file=TEST_ENV1 ;; + *) file='f oo' ;; + esac - run_tty_ $cmd "$file" >quoted.t || fail=1 + TEST_ENV1='f oo' run_tty_ $cmd "$file" >quoted.t || fail=1 cut -f$field- quoted.t >quoted || framework_failure_ # Note ls theoretically doesn't need isatty() for a specified QUOTING_STYLE # but it does need it to determine appropriate output format. - QUOTING_STYLE=literal run_tty_ $cmd "$file" >unquoted.t || fail=1 + TEST_ENV1='f oo' QUOTING_STYLE=literal run_tty_ $cmd "$file" \ + >unquoted.t || fail=1 cut -f$field- unquoted.t >unquoted || framework_failure_ env printf '%q\n' "$(cat unquoted)" >printf_quoted || framework_failure_ -- 2.55.0
