env/printenv: dedup the code

This commit is contained in:
Sylvestre Ledru
2025-12-25 16:31:25 +01:00
parent 502f3b17bf
commit 6a3b559fa6
3 changed files with 26 additions and 28 deletions
+3 -16
View File
@@ -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)]
@@ -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);
@@ -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);
}
+6 -12
View File
@@ -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";
@@ -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(());
}
@@ -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;
}
+17
View File
@@ -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};
@@ -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(())
}