summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-17 00:54:50 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-17 01:23:08 -0500
commit1327c2a7ba3b81fe69e4126270b2cfe24c8aa4ee (patch)
treebde52912ab1271d4dfca1787a74cfe6ccab54a64
parent51b30ef54d2953a89edda966f10f150b7ef81ee5 (diff)
downloadnbsh-1327c2a7ba3b81fe69e4126270b2cfe24c8aa4ee.tar.gz
nbsh-1327c2a7ba3b81fe69e4126270b2cfe24c8aa4ee.zip
make nbsh -c work
-rw-r--r--src/main.rs32
-rw-r--r--src/runner/mod.rs36
2 files changed, 42 insertions, 26 deletions
diff --git a/src/main.rs b/src/main.rs
index b65fb1e..48d2b2b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -24,17 +24,41 @@ mod prelude;
mod runner;
mod shell;
-async fn async_main() -> anyhow::Result<i32> {
+use prelude::*;
+
+async fn async_main(
+ shell_write: Option<&async_std::fs::File>,
+) -> anyhow::Result<i32> {
if std::env::args().nth(1).as_deref() == Some("-c") {
- return runner::run(std::env::args().nth(2).as_deref().unwrap())
- .await;
+ return runner::run(
+ std::env::args().nth(2).as_deref().unwrap(),
+ shell_write,
+ )
+ .await;
}
shell::main().await
}
fn main() {
- match async_std::task::block_on(async_main()) {
+ // 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(shell_write.as_ref())) {
Ok(code) => {
std::process::exit(code);
}
diff --git a/src/runner/mod.rs b/src/runner/mod.rs
index 0f02ef0..98894b3 100644
--- a/src/runner/mod.rs
+++ b/src/runner/mod.rs
@@ -69,16 +69,14 @@ enum Frame {
For(bool, usize, Vec<String>),
}
-pub async fn run(commands: &str) -> anyhow::Result<i32> {
- // Safety: we don't create File instances for or read/write data on fd
- // 3 anywhere else
- let shell_write = unsafe { async_std::fs::File::from_raw_fd(3) };
- cloexec(3)?;
-
+pub async fn run(
+ commands: &str,
+ shell_write: Option<&async_std::fs::File>,
+) -> anyhow::Result<i32> {
let mut env = Env::new_from_env()?;
- run_commands(commands, &mut env, &shell_write).await?;
+ run_commands(commands, &mut env, shell_write).await?;
let status = env.latest_status();
- write_event(&shell_write, Event::Exit(env)).await?;
+ write_event(shell_write, Event::Exit(env)).await?;
if let Some(signal) = status.signal() {
nix::sys::signal::raise(signal.try_into().unwrap())?;
@@ -89,7 +87,7 @@ pub async fn run(commands: &str) -> anyhow::Result<i32> {
async fn run_commands(
commands: &str,
env: &mut Env,
- shell_write: &async_std::fs::File,
+ shell_write: Option<&async_std::fs::File>,
) -> anyhow::Result<()> {
let commands = crate::parse::ast::Commands::parse(commands)?;
let commands = commands.commands();
@@ -194,7 +192,7 @@ async fn run_commands(
async fn run_pipeline(
pipeline: crate::parse::ast::Pipeline,
env: &mut Env,
- shell_write: &async_std::fs::File,
+ shell_write: Option<&async_std::fs::File>,
) -> anyhow::Result<()> {
write_event(shell_write, Event::RunPipeline(env.idx(), pipeline.span()))
.await?;
@@ -224,11 +222,13 @@ async fn run_pipeline(
}
async fn write_event(
- mut fh: &async_std::fs::File,
+ fh: Option<&async_std::fs::File>,
event: Event,
) -> anyhow::Result<()> {
- fh.write_all(&bincode::serialize(&event)?).await?;
- fh.flush().await?;
+ if let Some(mut fh) = fh {
+ fh.write_all(&bincode::serialize(&event)?).await?;
+ fh.flush().await?;
+ }
Ok(())
}
@@ -277,7 +277,7 @@ async fn wait_children(
pg: Option<nix::unistd::Pid>,
env: &Env,
io: &builtins::Io,
- shell_write: &async_std::fs::File,
+ shell_write: Option<&async_std::fs::File>,
) -> std::process::ExitStatus {
enum Res {
Child(nix::Result<nix::sys::wait::WaitStatus>),
@@ -514,14 +514,6 @@ fn setpgid_parent(
Ok(())
}
-fn cloexec(fd: std::os::unix::io::RawFd) -> anyhow::Result<()> {
- nix::fcntl::fcntl(
- fd,
- nix::fcntl::FcntlArg::F_SETFD(nix::fcntl::FdFlag::FD_CLOEXEC),
- )?;
- Ok(())
-}
-
fn id_to_pid(id: u32) -> nix::unistd::Pid {
nix::unistd::Pid::from_raw(id.try_into().unwrap())
}