1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

extract functions blocks to reduce cognitive complexity

This commit is contained in:
Ulrich Hornung 2024-03-22 22:17:48 +01:00
parent d9b2fec43d
commit 526cc8846c
No known key found for this signature in database
GPG key ID: 64EA3BAAF1BC0603

154
src/uu/env/src/env.rs vendored
View file

@ -292,7 +292,6 @@ impl EnvAppData {
Ok(all_args) Ok(all_args)
} }
#[allow(clippy::cognitive_complexity)]
fn run_env(&mut self, original_args: impl uucore::Args) -> UResult<()> { fn run_env(&mut self, original_args: impl uucore::Args) -> UResult<()> {
let original_args: Vec<OsString> = original_args.collect(); let original_args: Vec<OsString> = original_args.collect();
let args = self.process_all_string_arguments(&original_args)?; let args = self.process_all_string_arguments(&original_args)?;
@ -416,6 +415,86 @@ impl EnvAppData {
env::remove_var(name); env::remove_var(name);
} }
apply_specified_env_vars(&opts);
if opts.program.is_empty() {
// no program provided, so just dump all env vars to stdout
print_env(opts.line_ending);
} else {
return self.run_program(opts, do_debug_printing);
}
Ok(())
}
fn run_program(
&mut self,
opts: Options<'_>,
do_debug_printing: bool,
) -> Result<(), Box<dyn UError>> {
let prog = Cow::from(opts.program[0]);
let args = &opts.program[1..];
if do_debug_printing {
eprintln!("executable: {}", prog.quote());
for (i, arg) in args.iter().enumerate() {
eprintln!("arg[{}]: {}", i, arg.quote());
}
}
// we need to execute a command
/*
* On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
* (which ends up calling clone). Keep using the current process would be ideal, but the
* standard library contains many checks and fail-safes to ensure the process ends up being
* created. This is much simpler than dealing with the hassles of calling execvp directly.
*/
match process::Command::new(&*prog).args(args).status() {
Ok(exit) if !exit.success() => {
#[cfg(unix)]
if let Some(exit_code) = exit.code() {
return Err(exit_code.into());
} else {
// `exit.code()` returns `None` on Unix when the process is terminated by a signal.
// See std::os::unix::process::ExitStatusExt for more information. This prints out
// the interrupted process and the signal it received.
let signal_code = exit.signal().unwrap();
let signal = Signal::try_from(signal_code).unwrap();
// We have to disable any handler that's installed by default.
// This ensures that we exit on this signal.
// For example, `SIGSEGV` and `SIGBUS` have default handlers installed in Rust.
// We ignore the errors because there is not much we can do if that fails anyway.
// SAFETY: The function is unsafe because installing functions is unsafe, but we are
// just defaulting to default behavior and not installing a function. Hence, the call
// is safe.
let _ = unsafe {
sigaction(
signal,
&SigAction::new(SigHandler::SigDfl, SaFlags::empty(), SigSet::all()),
)
};
let _ = raise(signal);
}
return Err(exit.code().unwrap().into());
}
Err(ref err)
if (err.kind() == io::ErrorKind::NotFound)
|| (err.kind() == io::ErrorKind::InvalidInput) =>
{
return Err(self.make_error_no_such_file_or_dir(prog.deref()));
}
Err(e) => {
uucore::show_error!("unknown error: {:?}", e);
return Err(126.into());
}
Ok(_) => (),
}
Ok(())
}
}
fn apply_specified_env_vars(opts: &Options<'_>) {
// set specified env vars // set specified env vars
for (name, val) in &opts.sets { for (name, val) in &opts.sets {
/* /*
@ -446,79 +525,6 @@ impl EnvAppData {
} }
env::set_var(name, val); env::set_var(name, val);
} }
if opts.program.is_empty() {
// no program provided, so just dump all env vars to stdout
print_env(opts.line_ending);
} else {
// we need to execute a command
let prog = Cow::from(opts.program[0]);
let args = &opts.program[1..];
if do_debug_printing {
eprintln!("executable: {}", prog.quote());
for (i, arg) in args.iter().enumerate() {
eprintln!("arg[{}]: {}", i, arg.quote());
}
}
/*
* On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
* (which ends up calling clone). Keep using the current process would be ideal, but the
* standard library contains many checks and fail-safes to ensure the process ends up being
* created. This is much simpler than dealing with the hassles of calling execvp directly.
*/
match process::Command::new(&*prog).args(args).status() {
Ok(exit) if !exit.success() => {
#[cfg(unix)]
if let Some(exit_code) = exit.code() {
return Err(exit_code.into());
} else {
// `exit.code()` returns `None` on Unix when the process is terminated by a signal.
// See std::os::unix::process::ExitStatusExt for more information. This prints out
// the interrupted process and the signal it received.
let signal_code = exit.signal().unwrap();
let signal = Signal::try_from(signal_code).unwrap();
// We have to disable any handler that's installed by default.
// This ensures that we exit on this signal.
// For example, `SIGSEGV` and `SIGBUS` have default handlers installed in Rust.
// We ignore the errors because there is not much we can do if that fails anyway.
// SAFETY: The function is unsafe because installing functions is unsafe, but we are
// just defaulting to default behavior and not installing a function. Hence, the call
// is safe.
let _ = unsafe {
sigaction(
signal,
&SigAction::new(
SigHandler::SigDfl,
SaFlags::empty(),
SigSet::all(),
),
)
};
let _ = raise(signal);
}
#[cfg(not(unix))]
return Err(exit.code().unwrap().into());
}
Err(ref err)
if (err.kind() == io::ErrorKind::NotFound)
|| (err.kind() == io::ErrorKind::InvalidInput) =>
{
return Err(self.make_error_no_such_file_or_dir(prog.deref()));
}
Err(e) => {
uucore::show_error!("unknown error: {:?}", e);
return Err(126.into());
}
Ok(_) => (),
}
}
Ok(())
}
} }
#[uucore::main] #[uucore::main]