From 2472e512c344c77383b85714a343cf2b3ab5d637 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 18 Jan 2022 00:01:06 -0500 Subject: don't just assume that an open fd 3 means to send status updates now that we have subshells, we could have opened fd 3 on that subshell via redirects or whatever --- src/main.rs | 37 ++++++++++++++----------------------- src/shell/history/mod.rs | 2 +- 2 files changed, 15 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 3c57bf8..a7d3f4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,14 +31,22 @@ use prelude::*; struct Opt { #[structopt(short = "c")] command: Option, + + #[structopt(long)] + status_fd: Option, } -async fn async_main( - opt: Opt, - shell_write: Option<&async_std::fs::File>, -) -> anyhow::Result { +async fn async_main(opt: Opt) -> anyhow::Result { if let Some(command) = opt.command { - return runner::run(&command, shell_write).await; + let shell_write = opt.status_fd.and_then(|fd| { + nix::sys::stat::fstat(fd).ok().map(|_| { + // Safety: we don't create File instances for or read/write + // data on this fd anywhere else + unsafe { async_std::fs::File::from_raw_fd(fd) } + }) + }); + + return runner::run(&command, shell_write.as_ref()).await; } shell::main().await @@ -46,24 +54,7 @@ async fn async_main( #[paw::main] fn main(opt: Opt) { - // need to do this here because the async-std executor allocates some fds, - // and so in the case where we aren't being called from the main shell and - // fd 3 wasn't preallocated in advance, we need to be able to tell that - // before async-std opens something on fd 3 - let shell_write = if nix::sys::stat::fstat(3).is_ok() { - nix::fcntl::fcntl( - 3, - nix::fcntl::FcntlArg::F_SETFD(nix::fcntl::FdFlag::FD_CLOEXEC), - ) - .unwrap(); - // Safety: we don't create File instances for or read/write data on fd - // 3 anywhere else - Some(unsafe { async_std::fs::File::from_raw_fd(3) }) - } else { - None - }; - - match async_std::task::block_on(async_main(opt, shell_write.as_ref())) { + match async_std::task::block_on(async_main(opt)) { Ok(code) => { std::process::exit(code); } diff --git a/src/shell/history/mod.rs b/src/shell/history/mod.rs index ad83e92..60979b6 100644 --- a/src/shell/history/mod.rs +++ b/src/shell/history/mod.rs @@ -283,7 +283,7 @@ async fn spawn_commands( event_w: async_std::channel::Sender, ) -> anyhow::Result { let mut cmd = pty_process::Command::new(std::env::current_exe()?); - cmd.args(&["-c", cmdline]); + cmd.args(&["-c", cmdline, "--status-fd", "3"]); env.apply(&mut cmd); let (from_r, from_w) = nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC)?; // Safety: dup2 is an async-signal-safe function -- cgit v1.2.3-54-g00ecf