diff --git a/Cargo.lock b/Cargo.lock index a56b917575..2aa3433aa6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1031,11 +1031,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.2" +version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" dependencies = [ - "nix 0.27.1", + "nix", "windows-sys 0.52.0", ] @@ -1063,13 +1063,13 @@ dependencies = [ [[package]] name = "derive-new" -version = "0.5.9" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -2320,9 +2320,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" @@ -2450,15 +2450,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "miette" version = "7.2.0" @@ -2606,30 +2597,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", - "pin-utils", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "libc", -] - [[package]] name = "nix" version = "0.28.0" @@ -2714,7 +2681,7 @@ dependencies = [ "log", "miette", "mimalloc", - "nix 0.27.1", + "nix", "nu-cli", "nu-cmd-base", "nu-cmd-dataframe", @@ -2729,6 +2696,7 @@ dependencies = [ "nu-plugin", "nu-protocol", "nu-std", + "nu-system", "nu-test-support", "nu-utils", "openssl", @@ -2907,7 +2875,7 @@ dependencies = [ "mime_guess", "mockito", "native-tls", - "nix 0.27.1", + "nix", "notify-debouncer-full", "nu-ansi-term", "nu-cmd-base", @@ -3155,7 +3123,7 @@ dependencies = [ "libproc", "log", "mach2", - "nix 0.27.1", + "nix", "ntapi", "once_cell", "procfs", @@ -6087,7 +6055,7 @@ dependencies = [ "dunce", "glob", "libc", - "nix 0.28.0", + "nix", "once_cell", "os_display", "uucore_procs", @@ -6691,14 +6659,14 @@ dependencies = [ [[package]] name = "wl-clipboard-rs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57af79e973eadf08627115c73847392e6b766856ab8e3844a59245354b23d2fa" +checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" dependencies = [ "derive-new", "libc", "log", - "nix 0.26.4", + "nix", "os_pipe", "tempfile", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 4bc04300f7..c1bd1d9ac2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ mime = "0.3" mime_guess = "2.0" mockito = { version = "1.4", default-features = false } native-tls = "0.2" -nix = { version = "0.27", default-features = false } +nix = { version = "0.28", default-features = false } notify-debouncer-full = { version = "0.3", default-features = false } nu-ansi-term = "0.50.0" num-format = "0.4" @@ -178,6 +178,7 @@ nu-path = { path = "./crates/nu-path", version = "0.91.1" } nu-plugin = { path = "./crates/nu-plugin", optional = true, version = "0.91.1" } nu-protocol = { path = "./crates/nu-protocol", version = "0.91.1" } nu-std = { path = "./crates/nu-std", version = "0.91.1" } +nu-system = { path = "./crates/nu-system", version = "0.91.1" } nu-utils = { path = "./crates/nu-utils", version = "0.91.1" } reedline = { workspace = true, features = ["bashisms", "sqlite"] } diff --git a/crates/nu-system/src/foreground.rs b/crates/nu-system/src/foreground.rs index f2aa28b25a..56eec154cd 100644 --- a/crates/nu-system/src/foreground.rs +++ b/crates/nu-system/src/foreground.rs @@ -12,6 +12,9 @@ use std::{ }, }; +#[cfg(unix)] +pub use foreground_pgroup::stdin_fd; + /// A simple wrapper for [`std::process::Child`] /// /// It can only be created by [`ForegroundChild::spawn`]. @@ -98,15 +101,28 @@ impl Drop for ForegroundChild { #[cfg(unix)] mod foreground_pgroup { use nix::{ - libc, sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal}, unistd::{self, Pid}, }; use std::{ - os::unix::prelude::CommandExt, + os::{ + fd::{AsFd, BorrowedFd}, + unix::prelude::CommandExt, + }, process::{Child, Command}, }; + /// Alternative to having to call `std::io::stdin()` just to get the file descriptor of stdin + /// + /// # Safety + /// I/O safety of reading from `STDIN_FILENO` unclear. + /// + /// Currently only intended to access `tcsetpgrp` and `tcgetpgrp` with the I/O safe `nix` + /// interface. + pub unsafe fn stdin_fd() -> impl AsFd { + unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) } + } + pub fn prepare_command(external_command: &mut Command, existing_pgrp: u32) { unsafe { // Safety: @@ -154,12 +170,12 @@ mod foreground_pgroup { Pid::from_raw(existing_pgrp as i32) }; let _ = unistd::setpgid(pid, pgrp); - let _ = unistd::tcsetpgrp(libc::STDIN_FILENO, pgrp); + let _ = unistd::tcsetpgrp(unsafe { stdin_fd() }, pgrp); } /// Reset the foreground process group to the shell pub fn reset() { - if let Err(e) = unistd::tcsetpgrp(libc::STDIN_FILENO, unistd::getpgrp()) { + if let Err(e) = unistd::tcsetpgrp(unsafe { stdin_fd() }, unistd::getpgrp()) { eprintln!("ERROR: reset foreground id failed, tcsetpgrp result: {e:?}"); } } diff --git a/crates/nu-system/src/lib.rs b/crates/nu-system/src/lib.rs index 99e4365e40..bee037cb8b 100644 --- a/crates/nu-system/src/lib.rs +++ b/crates/nu-system/src/lib.rs @@ -7,6 +7,8 @@ pub mod os_info; #[cfg(target_os = "windows")] mod windows; +#[cfg(unix)] +pub use self::foreground::stdin_fd; pub use self::foreground::ForegroundChild; #[cfg(any(target_os = "android", target_os = "linux"))] pub use self::linux::*; diff --git a/src/terminal.rs b/src/terminal.rs index 6387a0ae50..4ea5aa0c36 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -57,7 +57,7 @@ pub(crate) fn acquire(interactive: bool) { } } // Set our possibly new pgid to be in control of terminal - let _ = unistd::tcsetpgrp(libc::STDIN_FILENO, shell_pgid); + let _ = unistd::tcsetpgrp(unsafe { nu_system::stdin_fd() }, shell_pgid); } } @@ -66,7 +66,7 @@ pub(crate) fn acquire(interactive: bool) { fn take_control() -> Pid { let shell_pgid = unistd::getpgrp(); - match unistd::tcgetpgrp(nix::libc::STDIN_FILENO) { + match unistd::tcgetpgrp(unsafe { nu_system::stdin_fd() }) { Ok(owner_pgid) if owner_pgid == shell_pgid => { // Common case, nothing to do return owner_pgid; @@ -91,14 +91,14 @@ fn take_control() -> Pid { } for _ in 0..4096 { - match unistd::tcgetpgrp(libc::STDIN_FILENO) { + match unistd::tcgetpgrp(unsafe { nu_system::stdin_fd() }) { Ok(owner_pgid) if owner_pgid == shell_pgid => { // success return owner_pgid; } Ok(owner_pgid) if owner_pgid == Pid::from_raw(0) => { // Zero basically means something like "not owned" and we can just take it - let _ = unistd::tcsetpgrp(libc::STDIN_FILENO, shell_pgid); + let _ = unistd::tcsetpgrp(unsafe { nu_system::stdin_fd() }, shell_pgid); } Err(Errno::ENOTTY) => { eprintln!("ERROR: no TTY for interactive shell"); @@ -123,7 +123,7 @@ extern "C" fn restore_terminal() { // `tcsetpgrp` and `getpgrp` are async-signal-safe let initial_pgid = Pid::from_raw(INITIAL_PGID.load(Ordering::Relaxed)); if initial_pgid.as_raw() > 0 && initial_pgid != unistd::getpgrp() { - let _ = unistd::tcsetpgrp(libc::STDIN_FILENO, initial_pgid); + let _ = unistd::tcsetpgrp(unsafe { nu_system::stdin_fd() }, initial_pgid); } }