diff --git a/src/uucore/src/lib/features/process.rs b/src/uucore/src/lib/features/process.rs index 57a2e8465..d6bd35043 100644 --- a/src/uucore/src/lib/features/process.rs +++ b/src/uucore/src/lib/features/process.rs @@ -8,10 +8,7 @@ // spell-checker:ignore pgrep pwait snice getpgrp use libc::{gid_t, pid_t, uid_t}; -#[cfg(not(target_os = "redox"))] -use nix::errno::Errno; -use nix::sys::signal::{self as nix_signal, SigHandler, Signal}; -use nix::unistd::Pid; +use rustix::process::{self as rprocess, Pid, Signal}; use std::io; use std::process::Child; use std::process::ExitStatus; @@ -20,35 +17,47 @@ use std::sync::atomic::AtomicBool; use std::thread; use std::time::{Duration, Instant}; +use crate::signals::csignal; + +/// Convert a raw signal number to a `Signal`, returning an error for invalid values. +fn signal_from_raw(sig: i32) -> io::Result { + if sig > 0 { + // SAFETY: we've checked the value is positive; the kernel will reject + // truly invalid signal numbers. + Ok(unsafe { Signal::from_raw_unchecked(sig) }) + } else { + Err(io::Error::from_raw_os_error(libc::EINVAL)) + } +} + /// `geteuid()` returns the effective user ID of the calling process. pub fn geteuid() -> uid_t { - nix::unistd::geteuid().as_raw() + rprocess::geteuid().as_raw() } /// `getpgrp()` returns the process group ID of the calling process. -/// It is a trivial wrapper over nix::unistd::getpgrp. pub fn getpgrp() -> pid_t { - nix::unistd::getpgrp().as_raw() + rprocess::getpgrp().as_raw_nonzero().get() } /// `getegid()` returns the effective group ID of the calling process. pub fn getegid() -> gid_t { - nix::unistd::getegid().as_raw() + rprocess::getegid().as_raw() } /// `getgid()` returns the real group ID of the calling process. pub fn getgid() -> gid_t { - nix::unistd::getgid().as_raw() + rprocess::getgid().as_raw() } /// `getuid()` returns the real user ID of the calling process. pub fn getuid() -> uid_t { - nix::unistd::getuid().as_raw() + rprocess::getuid().as_raw() } /// `getpid()` returns the pid of the calling process. pub fn getpid() -> pid_t { - nix::unistd::getpid().as_raw() + rprocess::getpid().as_raw_nonzero().get() } /// `getsid()` returns the session ID of the process with process ID pid. @@ -57,22 +66,23 @@ pub fn getpid() -> pid_t { /// /// # Error /// -/// - [Errno::EPERM] A process with process ID pid exists, but it is not in the same session as the calling process, and the implementation considers this an error. -/// - [Errno::ESRCH] No process with process ID pid was found. -/// +/// - EPERM: A process with process ID pid exists, but it is not in the same session as the calling process, and the implementation considers this an error. +/// - ESRCH: No process with process ID pid was found. /// /// # Platform /// /// This function only support standard POSIX implementation platform, /// so some system such as redox doesn't supported. #[cfg(not(target_os = "redox"))] -pub fn getsid(pid: i32) -> Result { +pub fn getsid(pid: i32) -> io::Result { let pid = if pid == 0 { None } else { - Some(Pid::from_raw(pid)) + Some(Pid::from_raw(pid).ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?) }; - nix::unistd::getsid(pid).map(Pid::as_raw) + rprocess::getsid(pid) + .map(|p| p.as_raw_nonzero().get()) + .map_err(Into::into) } /// Missing methods for Child objects @@ -97,15 +107,15 @@ pub trait ChildExt { impl ChildExt for Child { fn send_signal(&mut self, signal: usize) -> io::Result<()> { - let pid = Pid::from_raw(self.id() as pid_t); - let result = if signal == 0 { - nix_signal::kill(pid, None) + let pid = Pid::from_raw(self.id() as pid_t) + .ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?; + if signal == 0 { + rprocess::test_kill_process(pid)?; } else { - let signal = Signal::try_from(signal as i32) - .map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?; - nix_signal::kill(pid, Some(signal)) - }; - result.map_err(|e| io::Error::from_raw_os_error(e as i32)) + let sig = signal_from_raw(signal as i32)?; + rprocess::kill_process(pid, sig)?; + } + Ok(()) } fn send_signal_group(&mut self, signal: usize) -> io::Result<()> { @@ -118,20 +128,19 @@ impl ChildExt for Child { // Signal 0 is special - it just checks if process exists, doesn't send anything. // No need to manipulate signal handlers for it. if signal == 0 { - return nix_signal::kill(Pid::from_raw(0), None) - .map_err(|e| io::Error::from_raw_os_error(e as i32)); + return rprocess::test_kill_current_process_group().map_err(Into::into); } - let signal = Signal::try_from(signal as i32) - .map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?; + let sig = signal_from_raw(signal as i32)?; // Ignore the signal temporarily so we don't receive it ourselves. - let old_handler = unsafe { nix_signal::signal(signal, SigHandler::SigIgn) } - .map_err(|e| io::Error::from_raw_os_error(e as i32))?; - let result = nix_signal::kill(Pid::from_raw(0), Some(signal)); + let old_handler = unsafe { + csignal::set_signal_handler(signal as libc::c_int, csignal::SigHandler::SigIgn) + }?; + let result = rprocess::kill_current_process_group(sig); // Restore the old handler - let _ = unsafe { nix_signal::signal(signal, old_handler) }; - result.map_err(|e| io::Error::from_raw_os_error(e as i32)) + let _ = unsafe { csignal::set_signal_handler(signal as libc::c_int, old_handler) }; + result.map_err(Into::into) } fn wait_or_timeout(