diff --git a/Cargo.lock b/Cargo.lock index e7cba7350..fe0ee52a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4108,7 +4108,6 @@ version = "0.5.0" dependencies = [ "clap", "fluent", - "nix", "utmp-classic", "uucore", ] @@ -4144,7 +4143,6 @@ version = "0.5.0" dependencies = [ "clap", "fluent", - "nix", "uucore", ] diff --git a/src/uu/users/Cargo.toml b/src/uu/users/Cargo.toml index ca0e91c3b..c86f0146c 100644 --- a/src/uu/users/Cargo.toml +++ b/src/uu/users/Cargo.toml @@ -24,9 +24,8 @@ path = "src/users.rs" [dependencies] clap = { workspace = true } -uucore = { workspace = true, features = ["utmpx"] } +uucore = { workspace = true, features = ["utmpx", "process"] } fluent = { workspace = true } -nix = { workspace = true, features = ["signal"] } [target.'cfg(target_os = "openbsd")'.dependencies] utmp-classic = { workspace = true } diff --git a/src/uu/users/src/users.rs b/src/uu/users/src/users.rs index f39040cb7..79343d254 100644 --- a/src/uu/users/src/users.rs +++ b/src/uu/users/src/users.rs @@ -10,12 +10,10 @@ use std::path::Path; use clap::builder::ValueParser; use clap::{Arg, Command}; -#[cfg(not(target_os = "openbsd"))] -use nix::sys::signal::kill; -#[cfg(not(target_os = "openbsd"))] -use nix::unistd::Pid; use uucore::error::UResult; use uucore::format_usage; +#[cfg(not(target_os = "openbsd"))] +use uucore::process::pid_is_alive; use uucore::translate; #[cfg(target_os = "openbsd")] @@ -37,20 +35,6 @@ fn get_long_usage() -> String { translate!("users-long-usage", "default_path" => default_path) } -#[inline] -#[cfg(not(target_os = "openbsd"))] -fn pid_is_alive(pid: i32) -> bool { - if pid <= 0 { - return true; - } - - match kill(Pid::from_raw(pid), None) { - Ok(()) => true, - Err(nix::errno::Errno::ESRCH) => false, - Err(_) => true, - } -} - #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?; diff --git a/src/uu/who/Cargo.toml b/src/uu/who/Cargo.toml index 4ca101084..8a8ac22bd 100644 --- a/src/uu/who/Cargo.toml +++ b/src/uu/who/Cargo.toml @@ -25,9 +25,8 @@ path = "src/who.rs" [dependencies] clap = { workspace = true } -uucore = { workspace = true, features = ["utmpx"] } +uucore = { workspace = true, features = ["utmpx", "process"] } fluent = { workspace = true } -nix = { workspace = true, features = ["signal"] } [[bin]] name = "who" diff --git a/src/uu/who/src/platform/unix.rs b/src/uu/who/src/platform/unix.rs index 5868d681a..1df818a91 100644 --- a/src/uu/who/src/platform/unix.rs +++ b/src/uu/who/src/platform/unix.rs @@ -11,11 +11,10 @@ use crate::uu_app; use uucore::display::Quotable; use uucore::error::{FromIo, UResult}; use uucore::libc::{S_IWGRP, STDIN_FILENO, ttyname}; +#[cfg(not(target_os = "openbsd"))] +use uucore::process::pid_is_alive; use uucore::translate; -use nix::sys::signal::kill; -use nix::unistd::Pid; - use uucore::utmpx::{self, UtmpxRecord, time}; use std::borrow::Cow; @@ -180,20 +179,6 @@ fn time_string(ut: &UtmpxRecord) -> String { ut.login_time().format(&time_format).unwrap() } -#[inline] -#[cfg(not(target_os = "openbsd"))] -fn pid_is_alive(pid: i32) -> bool { - if pid <= 0 { - return true; - } - - match kill(Pid::from_raw(pid), None) { - Ok(()) => true, - Err(nix::errno::Errno::ESRCH) => false, - Err(_) => true, - } -} - #[inline] fn current_tty() -> String { unsafe { diff --git a/src/uucore/src/lib/features/process.rs b/src/uucore/src/lib/features/process.rs index 55e8c3648..02d23231f 100644 --- a/src/uucore/src/lib/features/process.rs +++ b/src/uucore/src/lib/features/process.rs @@ -51,6 +51,31 @@ pub fn getpid() -> pid_t { unsafe { libc::getpid() } } +/// Check if a process with the given PID is alive. +/// +/// Uses `kill(pid, 0)` which sends signal 0 (null signal) to check process existence +/// without actually sending a signal. This is a standard POSIX technique for checking +/// if a process exists. +/// +/// Returns `true` if: +/// - The process exists (kill returns 0) +/// - We lack permission to signal the process (errno != ESRCH) +/// This means the process exists but we can't signal it +/// +/// Returns `false` only if: +/// - errno is ESRCH (No such process), confirming the process doesn't exist +/// +/// PIDs <= 0 are considered alive for compatibility with utmp records that may +/// contain special or invalid PID values. +#[cfg(not(target_os = "openbsd"))] +pub fn pid_is_alive(pid: i32) -> bool { + if pid <= 0 { + return true; + } + + unsafe { libc::kill(pid, 0) == 0 || *libc::__errno_location() != libc::ESRCH } +} + /// `getsid()` returns the session ID of the process with process ID pid. /// /// If pid is 0, getsid() returns the session ID of the calling process.