diff --git a/Cargo.lock b/Cargo.lock index c86edc12a2..6003430696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3311,7 +3311,6 @@ name = "uu_yes" version = "0.0.17" dependencies = [ "clap", - "libc", "nix", "uucore", ] diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index 96c318afd4..ca703b3616 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -11,7 +11,9 @@ use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write}; use std::path::PathBuf; use uucore::display::Quotable; use uucore::error::UResult; -use uucore::{format_usage, help_about, help_section, help_usage, show_error}; +use uucore::{ + format_usage, help_about, help_section, help_usage, show_error, signals::enable_pipe_errors, +}; // spell-checker:ignore nopipe @@ -150,21 +152,6 @@ fn ignore_interrupts() -> Result<()> { Ok(()) } -#[cfg(unix)] -fn enable_pipe_errors() -> Result<()> { - let ret = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) }; - if ret == libc::SIG_ERR { - return Err(Error::new(ErrorKind::Other, "")); - } - Ok(()) -} - -#[cfg(not(unix))] -fn enable_pipe_errors() -> Result<()> { - // Do nothing. - Ok(()) -} - fn tee(options: &Options) -> Result<()> { if options.ignore_interrupts { ignore_interrupts()?; diff --git a/src/uu/timeout/src/timeout.rs b/src/uu/timeout/src/timeout.rs index fe342727ba..8b4809cc77 100644 --- a/src/uu/timeout/src/timeout.rs +++ b/src/uu/timeout/src/timeout.rs @@ -17,7 +17,7 @@ use std::time::Duration; use uucore::display::Quotable; use uucore::error::{UClapError, UResult, USimpleError, UUsageError}; use uucore::process::ChildExt; -use uucore::signals::{signal_by_name_or_value, signal_name_by_value}; +use uucore::signals::{enable_pipe_errors, signal_by_name_or_value, signal_name_by_value}; use uucore::{format_usage, show_error}; static ABOUT: &str = "Start COMMAND, and kill it if still running after DURATION."; @@ -285,21 +285,6 @@ fn preserve_signal_info(signal: libc::c_int) -> libc::c_int { signal } -#[cfg(unix)] -fn enable_pipe_errors() -> std::io::Result<()> { - let ret = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) }; - if ret == libc::SIG_ERR { - return Err(std::io::Error::new(std::io::ErrorKind::Other, "")); - } - Ok(()) -} - -#[cfg(not(unix))] -fn enable_pipe_errors() -> std::io::Result<()> { - // Do nothing. - Ok(()) -} - /// TODO: Improve exit codes, and make them consistent with the GNU Coreutils exit codes. fn timeout( diff --git a/src/uu/yes/Cargo.toml b/src/uu/yes/Cargo.toml index cf120f2e0b..4d8ac1ffdf 100644 --- a/src/uu/yes/Cargo.toml +++ b/src/uu/yes/Cargo.toml @@ -16,11 +16,10 @@ path = "src/yes.rs" [dependencies] clap = { workspace=true } -libc = { workspace=true } uucore = { workspace=true, features=["pipes"] } -[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -nix = { workspace=true } +[target.'cfg(unix)'.dependencies] +nix = { workspace=true, features = ["signal"] } [[bin]] name = "yes" diff --git a/src/uu/yes/src/yes.rs b/src/uu/yes/src/yes.rs index 714bdcac51..4d9a8ce390 100644 --- a/src/uu/yes/src/yes.rs +++ b/src/uu/yes/src/yes.rs @@ -8,11 +8,12 @@ /* last synced with: yes (GNU coreutils) 8.13 */ use std::borrow::Cow; -use std::io::{self, Result, Write}; +use std::io::{self, Write}; use clap::{Arg, ArgAction, Command}; +#[cfg(unix)] use uucore::error::{UResult, USimpleError}; -use uucore::{format_usage, help_about, help_usage}; +use uucore::{format_usage, help_about, help_usage, signals::enable_pipe_errors}; #[cfg(any(target_os = "linux", target_os = "android"))] mod splice; @@ -69,21 +70,6 @@ fn prepare_buffer<'a>(input: &'a str, buffer: &'a mut [u8; BUF_SIZE]) -> &'a [u8 } } -#[cfg(unix)] -fn enable_pipe_errors() -> Result<()> { - let ret = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) }; - if ret == libc::SIG_ERR { - return Err(io::Error::new(io::ErrorKind::Other, "")); - } - Ok(()) -} - -#[cfg(not(unix))] -fn enable_pipe_errors() -> Result<()> { - // Do nothing. - Ok(()) -} - pub fn exec(bytes: &[u8]) -> io::Result<()> { let stdout = io::stdout(); let mut stdout = stdout.lock(); diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index f5bec90539..4ca3941db7 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -49,7 +49,7 @@ sm3 = { workspace=true } [target.'cfg(unix)'.dependencies] walkdir = { workspace=true, optional=true } -nix = { workspace=true, features = ["fs", "uio", "zerocopy"] } +nix = { workspace=true, features = ["fs", "uio", "zerocopy", "signal"] } [dev-dependencies] clap = { workspace=true } diff --git a/src/uucore/src/lib/features/signals.rs b/src/uucore/src/lib/features/signals.rs index b92ecf764d..5ddb71d153 100644 --- a/src/uucore/src/lib/features/signals.rs +++ b/src/uucore/src/lib/features/signals.rs @@ -7,6 +7,10 @@ // spell-checker:ignore (vars/api) fcntl setrlimit setitimer // spell-checker:ignore (vars/signals) ABRT ALRM CHLD SEGV SIGABRT SIGALRM SIGBUS SIGCHLD SIGCONT SIGEMT SIGFPE SIGHUP SIGILL SIGINFO SIGINT SIGIO SIGIOT SIGKILL SIGPIPE SIGPROF SIGPWR SIGQUIT SIGSEGV SIGSTOP SIGSYS SIGTERM SIGTRAP SIGTSTP SIGTHR SIGTTIN SIGTTOU SIGURG SIGUSR SIGVTALRM SIGWINCH SIGXCPU SIGXFSZ STKFLT PWR THR TSTP TTIN TTOU VTALRM XCPU XFSZ +use nix::sys::signal::{ + signal, SigHandler::SigDfl, SigHandler::SigIgn, Signal::SIGINT, Signal::SIGPIPE, +}; +use std::io::{Error, ErrorKind, Result}; pub static DEFAULT_SIGNAL: usize = 15; @@ -196,6 +200,36 @@ pub fn signal_name_by_value(signal_value: usize) -> Option<&'static str> { ALL_SIGNALS.get(signal_value).copied() } +#[cfg(unix)] +pub fn enable_pipe_errors() -> Result<()> { + // SAFETY: this function is safe as long as we do not use a custom SigHandler -- we use the default one. + match unsafe { signal(SIGPIPE, SigDfl) } { + Ok(_) => Ok(()), + _ => Err(Error::from(ErrorKind::Other)), + } +} + +#[cfg(not(unix))] +pub fn enable_pipe_errors() -> Result<()> { + // Do nothing. + Ok(()) +} + +#[cfg(unix)] +pub fn ignore_interrupts() -> Result<()> { + // SAFETY: this function is safe as long as we do not use a custom SigHandler -- we use the default one. + match unsafe { signal(SIGINT, SigIgn) } { + Ok(_) => Ok(()), + _ => Err(Error::from(ErrorKind::Other)), + } +} + +#[cfg(not(unix))] +pub fn ignore_interrupts() -> Result<()> { + // Do nothing. + Ok(()) +} + #[test] fn signal_by_value() { assert_eq!(signal_by_name_or_value("0"), Some(0));