summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-18 00:01:06 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-18 00:01:06 -0500
commit2472e512c344c77383b85714a343cf2b3ab5d637 (patch)
tree6c927717762a3b03a5d6d9956d19bb80173d512c /src
parenta7b16850f2437b015bcec8919586c4d4b070a35e (diff)
downloadnbsh-2472e512c344c77383b85714a343cf2b3ab5d637.tar.gz
nbsh-2472e512c344c77383b85714a343cf2b3ab5d637.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/main.rs37
-rw-r--r--src/shell/history/mod.rs2
2 files changed, 15 insertions, 24 deletions
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<String>,
+
+ #[structopt(long)]
+ status_fd: Option<std::os::unix::io::RawFd>,
}
-async fn async_main(
- opt: Opt,
- shell_write: Option<&async_std::fs::File>,
-) -> anyhow::Result<i32> {
+async fn async_main(opt: Opt) -> anyhow::Result<i32> {
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<Event>,
) -> anyhow::Result<async_std::process::ExitStatus> {
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