Repository navigation
printenv: Honor QUOTING_STYLE environment variable
#14857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,17 +4,20 @@ | |
| // file that was distributed with this source code. | ||
|
|
||
| use std::env; | ||
| use std::io::Write; | ||
| use std::io::{IsTerminal, Write}; | ||
|
|
||
| use clap::{Arg, ArgAction, Command}; | ||
|
|
||
| use uucore::display::{OsWrite, print_all_env_vars}; | ||
| use uucore::display::{OsWrite, print_all_env_vars, print_all_env_vars_quoted}; | ||
| use uucore::error::UResult; | ||
| use uucore::i18n::get_ctype_encoding; | ||
| use uucore::line_ending::LineEnding; | ||
| use uucore::quoting_style::{ | ||
| QuotingStyle, escape_name, parser as qs_parser, quoting_style_from_env, | ||
| }; | ||
| use uucore::{format_usage, translate}; | ||
|
|
||
| static OPT_NULL: &str = "null"; | ||
|
|
||
| static ARG_VARIABLES: &str = "variables"; | ||
|
|
||
| #[uucore::main(no_signals)] | ||
|
|
@@ -26,14 +29,34 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { | |
| .map(|v| v.map(ToString::to_string).collect()) | ||
| .unwrap_or_default(); | ||
|
|
||
| let maybe_quoting_style = matches | ||
| .get_one::<String>(qs_parser::QUOTING_STYLE) | ||
| .and_then(QuotingStyle::parse) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an invalid |
||
| .or_else(|| { | ||
| std::io::stdout() | ||
| .is_terminal() // quoting style from env var is only used in TTY | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why only on a tty? stat and ls use QUOTING_STYLE whatever stdout is
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only following GNU behavior here |
||
| .then(quoting_style_from_env) | ||
| .flatten() | ||
| }); | ||
|
|
||
| let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL)); | ||
|
|
||
| if variables.is_empty() { | ||
| print_all_env_vars(separator)?; | ||
| if let Some(quoting_style) = maybe_quoting_style { | ||
| print_all_env_vars_quoted( | ||
| std::io::stdout(), | ||
| separator, | ||
| quoting_style, | ||
| get_ctype_encoding(), | ||
| )?; | ||
| } else { | ||
| print_all_env_vars(std::io::stdout(), separator)?; | ||
| } | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let mut error_found = false; | ||
| let ctype = get_ctype_encoding(); | ||
| for env_var in variables { | ||
| // we silently ignore a=b as variable but we trigger an error | ||
| if env_var.contains('=') { | ||
|
|
@@ -42,6 +65,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { | |
| } | ||
| if let Some(var) = env::var_os(env_var) { | ||
| let mut stdout = std::io::stdout().lock(); | ||
|
|
||
| let var = if let Some(qs) = maybe_quoting_style { | ||
| escape_name(&var, qs, ctype) | ||
| } else { | ||
| var | ||
| }; | ||
|
|
||
| stdout.write_all_os(&var)?; | ||
| write!(stdout, "{separator}")?; | ||
| } else { | ||
|
|
@@ -66,6 +96,7 @@ pub fn uu_app() -> Command { | |
| .help(translate!("printenv-help-null")) | ||
| .action(ArgAction::SetTrue), | ||
| ) | ||
| .arg(qs_parser::clap_quoting_argument()) | ||
| .arg( | ||
| Arg::new(ARG_VARIABLES) | ||
| .action(ArgAction::Append) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,12 @@ use std::{env, fmt}; | |
| // These used to be defined here, but they live in their own crate now. | ||
| pub use os_display::{Quotable, Quoted}; | ||
|
|
||
| #[cfg(feature = "quoting-style")] | ||
| use crate::{ | ||
| i18n::UEncoding, | ||
| quoting_style::{QuotingStyle, escape_name}, | ||
| }; | ||
|
|
||
| /// Print a path (or `OsStr`-like object) directly to stdout, with a trailing newline, | ||
| /// without losing any information if its encoding is invalid. | ||
| /// | ||
|
|
@@ -119,13 +125,31 @@ impl OsWrite for Box<dyn OsWrite> { | |
| /// | ||
| /// This function handles non-UTF-8 environment variable names and values correctly by using | ||
| /// raw bytes on Unix systems. | ||
| pub fn print_all_env_vars<T: fmt::Display>(line_ending: T) -> io::Result<()> { | ||
| let mut stdout = io::stdout().lock(); | ||
| pub fn print_all_env_vars<W: OsWrite, T: fmt::Display>(mut w: W, line_ending: T) -> io::Result<()> { | ||
| for (name, value) in env::vars_os() { | ||
| stdout.write_all_os(&name)?; | ||
| stdout.write_all(b"=")?; | ||
| stdout.write_all_os(&value)?; | ||
| write!(stdout, "{line_ending}")?; | ||
| w.write_all_os(&name)?; | ||
| w.write_all(b"=")?; | ||
|
|
||
| w.write_all_os(&value)?; | ||
| write!(w, "{line_ending}")?; | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| /// Equivalent to [`print_all_env_vars`] that quotes | ||
| #[cfg(feature = "quoting-style")] | ||
| pub fn print_all_env_vars_quoted<W: OsWrite, T: fmt::Display>( | ||
| mut w: W, | ||
| line_ending: T, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why gate the whole function behind quoting-style? only the escaping needs it
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, created a specific |
||
| quoting_style: QuotingStyle, | ||
| encoding: UEncoding, | ||
| ) -> io::Result<()> { | ||
| for (name, value) in env::vars_os() { | ||
| w.write_all_os(&escape_name(&name, quoting_style, encoding))?; | ||
| w.write_all(b"=")?; | ||
|
|
||
| w.write_all_os(&escape_name(&value, quoting_style, encoding))?; | ||
| write!(w, "{line_ending}")?; | ||
| } | ||
| Ok(()) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you please list the accepted values in the help, like ls does?