Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ use nix::sys::signal::{SigHandler::SigIgn, Signal, signal};
use std::borrow::Cow;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::io;
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
#[cfg(unix)]
use std::os::unix::process::CommandExt;

use uucore::display::{OsWrite, Quotable};
use uucore::display::{Quotable, print_all_env_vars};
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError};
use uucore::line_ending::LineEnding;
#[cfg(unix)]
Expand Down Expand Up @@ -99,19 +99,6 @@ struct Options<'a> {
ignore_signal: Vec<usize>,
}

/// print `name=value` env pairs on screen
fn print_env(line_ending: LineEnding) -> io::Result<()> {
let stdout_raw = io::stdout();
let mut stdout = stdout_raw.lock();
for (n, v) in env::vars_os() {
stdout.write_all_os(&n)?;
stdout.write_all(b"=")?;
stdout.write_all_os(&v)?;
write!(stdout, "{line_ending}")?;
}
Ok(())
}

fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a OsStr) -> UResult<bool> {
// is it a NAME=VALUE like opt ?
let wrap = NativeStr::<'a>::new(opt);
Expand Down Expand Up @@ -552,7 +539,7 @@ impl EnvAppData {

if opts.program.is_empty() {
// no program provided, so just dump all env vars to stdout
print_env(opts.line_ending)?;
print_all_env_vars(opts.line_ending)?;
} else {
return self.run_program(&opts, self.do_debug_printing);
}
Expand Down
18 changes: 6 additions & 12 deletions src/uu/printenv/src/printenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use std::io::Write;

use clap::{Arg, ArgAction, Command};

use uucore::display::{OsWrite, print_all_env_vars};
use uucore::error::UResult;
use uucore::line_ending::LineEnding;
use uucore::{format_usage, os_str_as_bytes, translate};
use uucore::{format_usage, translate};

static OPT_NULL: &str = "null";

Expand All @@ -28,14 +29,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL));

if variables.is_empty() {
for (env_var, value) in env::vars_os() {
let env_bytes = os_str_as_bytes(&env_var)?;
let val_bytes = os_str_as_bytes(&value)?;
std::io::stdout().lock().write_all(env_bytes)?;
print!("=");
std::io::stdout().lock().write_all(val_bytes)?;
print!("{separator}");
}
print_all_env_vars(separator)?;
return Ok(());
}

Expand All @@ -47,9 +41,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
continue;
}
if let Some(var) = env::var_os(env_var) {
let val_bytes = os_str_as_bytes(&var)?;
std::io::stdout().lock().write_all(val_bytes)?;
print!("{separator}");
let mut stdout = std::io::stdout().lock();
stdout.write_all_os(&var)?;
write!(stdout, "{separator}")?;
} else {
error_found = true;
}
Expand Down
17 changes: 17 additions & 0 deletions src/uucore/src/lib/mods/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
//! # Ok::<(), std::io::Error>(())
//! ```

use std::env;
use std::ffi::OsStr;
use std::fmt;
use std::fs::File;
use std::io::{self, BufWriter, Stdout, StdoutLock, Write as IoWrite};

Expand Down Expand Up @@ -117,3 +119,18 @@ impl OsWrite for Box<dyn OsWrite> {
this.write_all_os(buf)
}
}

/// Print all environment variables in the format `name=value` with the specified line ending.
///
/// 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();
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}")?;
}
Ok(())
}
13 changes: 13 additions & 0 deletions tests/by-util/test_printenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,16 @@ fn test_non_utf8_value() {
);
result.stdout_is_bytes(b"/tmp/lib.so\xff\n");
}

#[test]
#[cfg(unix)]
fn test_non_utf8_env_vars() {
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;

let non_utf8_value = OsString::from_vec(b"hello\x80world".to_vec());
new_ucmd!()
.env("NON_UTF8_VAR", &non_utf8_value)
.succeeds()
.stdout_contains_bytes(b"NON_UTF8_VAR=hello\x80world");
}
Loading