summaryrefslogtreecommitdiffstats
path: root/src/pipeline/builtins/command.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-08 07:55:16 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-08 07:55:16 -0500
commit778b1f751a036fc025026be883e336074bde7d9b (patch)
treea2e301ed4b005dbd530053d2eb8f23fef7b4f556 /src/pipeline/builtins/command.rs
parent22769358621eae3d1e65cff3d402f71b6c1cec4b (diff)
downloadnbsh-778b1f751a036fc025026be883e336074bde7d9b.tar.gz
nbsh-778b1f751a036fc025026be883e336074bde7d9b.zip
share stdin/stdout/stderr handles among builtins in a pipeline
Diffstat (limited to 'src/pipeline/builtins/command.rs')
-rw-r--r--src/pipeline/builtins/command.rs108
1 files changed, 66 insertions, 42 deletions
diff --git a/src/pipeline/builtins/command.rs b/src/pipeline/builtins/command.rs
index 83d39cb..8119a55 100644
--- a/src/pipeline/builtins/command.rs
+++ b/src/pipeline/builtins/command.rs
@@ -23,6 +23,25 @@ impl Command {
}
}
+ pub fn new_with_io(
+ exe: crate::parse::Exe,
+ io: Io,
+ ) -> Result<Self, crate::parse::Exe> {
+ if let Some(s) = exe.exe().to_str() {
+ if let Some(f) = super::BUILTINS.get(s) {
+ Ok(Self {
+ exe,
+ f,
+ cfg: Cfg::new_with_io(io),
+ })
+ } else {
+ Err(exe)
+ }
+ } else {
+ Err(exe)
+ }
+ }
+
pub fn stdin(&mut self, fh: std::fs::File) {
self.cfg.io.set_stdin(fh);
}
@@ -69,6 +88,10 @@ impl Cfg {
}
}
+ fn new_with_io(io: Io) -> Self {
+ Self { io, pre_exec: None }
+ }
+
pub fn io(&self) -> &Io {
&self.io
}
@@ -93,6 +116,7 @@ impl Cfg {
}
}
+#[derive(Debug, Clone)]
pub struct Io {
fds: std::collections::HashMap<
std::os::unix::io::RawFd,
@@ -101,24 +125,19 @@ pub struct Io {
}
impl Io {
- fn new() -> Self {
- let mut fds = std::collections::HashMap::new();
- fds.insert(0, crate::mutex::new(unsafe { File::input(0) }));
- fds.insert(1, crate::mutex::new(unsafe { File::output(1) }));
- fds.insert(2, crate::mutex::new(unsafe { File::output(2) }));
- Self { fds }
+ pub fn new() -> Self {
+ Self {
+ fds: std::collections::HashMap::new(),
+ }
}
fn stdin(&self) -> Option<crate::mutex::Mutex<File>> {
self.fds.get(&0).map(async_std::sync::Arc::clone)
}
- fn set_stdin<T: std::os::unix::io::IntoRawFd>(&mut self, stdin: T) {
+ pub fn set_stdin<T: std::os::unix::io::IntoRawFd>(&mut self, stdin: T) {
if let Some(file) = self.fds.remove(&0) {
- let file = crate::mutex::unwrap(file);
- if file.as_raw_fd() <= 2 {
- let _ = file.into_raw_fd();
- }
+ File::maybe_drop(file);
}
self.fds.insert(
0,
@@ -130,12 +149,9 @@ impl Io {
self.fds.get(&1).map(async_std::sync::Arc::clone)
}
- fn set_stdout<T: std::os::unix::io::IntoRawFd>(&mut self, stdout: T) {
+ pub fn set_stdout<T: std::os::unix::io::IntoRawFd>(&mut self, stdout: T) {
if let Some(file) = self.fds.remove(&1) {
- let file = crate::mutex::unwrap(file);
- if file.as_raw_fd() <= 2 {
- let _ = file.into_raw_fd();
- }
+ File::maybe_drop(file);
}
self.fds.insert(
1,
@@ -147,12 +163,9 @@ impl Io {
self.fds.get(&2).map(async_std::sync::Arc::clone)
}
- fn set_stderr<T: std::os::unix::io::IntoRawFd>(&mut self, stderr: T) {
+ pub fn set_stderr<T: std::os::unix::io::IntoRawFd>(&mut self, stderr: T) {
if let Some(file) = self.fds.remove(&2) {
- let file = crate::mutex::unwrap(file);
- if file.as_raw_fd() <= 2 {
- let _ = file.into_raw_fd();
- }
+ File::maybe_drop(file);
}
self.fds.insert(
2,
@@ -221,27 +234,33 @@ impl Io {
pub fn setup_command(mut self, cmd: &mut crate::pipeline::Command) {
if let Some(stdin) = self.fds.remove(&0) {
- let stdin = crate::mutex::unwrap(stdin).into_raw_fd();
- if stdin != 0 {
- // Safety: TODO this is likely unsafe
- cmd.stdin(unsafe { std::fs::File::from_raw_fd(stdin) });
- self.fds.remove(&0);
+ if let Some(stdin) = crate::mutex::unwrap(stdin) {
+ let stdin = stdin.into_raw_fd();
+ if stdin != 0 {
+ // Safety: TODO this is likely unsafe
+ cmd.stdin(unsafe { std::fs::File::from_raw_fd(stdin) });
+ self.fds.remove(&0);
+ }
}
}
if let Some(stdout) = self.fds.remove(&1) {
- let stdout = crate::mutex::unwrap(stdout).into_raw_fd();
- if stdout != 1 {
- // Safety: TODO this is likely unsafe
- cmd.stdout(unsafe { std::fs::File::from_raw_fd(stdout) });
- self.fds.remove(&1);
+ if let Some(stdout) = crate::mutex::unwrap(stdout) {
+ let stdout = stdout.into_raw_fd();
+ if stdout != 1 {
+ // Safety: TODO this is likely unsafe
+ cmd.stdout(unsafe { std::fs::File::from_raw_fd(stdout) });
+ self.fds.remove(&1);
+ }
}
}
if let Some(stderr) = self.fds.remove(&2) {
- let stderr = crate::mutex::unwrap(stderr).into_raw_fd();
- if stderr != 2 {
- // Safety: TODO this is likely unsafe
- cmd.stderr(unsafe { std::fs::File::from_raw_fd(stderr) });
- self.fds.remove(&2);
+ if let Some(stderr) = crate::mutex::unwrap(stderr) {
+ let stderr = stderr.into_raw_fd();
+ if stderr != 2 {
+ // Safety: TODO this is likely unsafe
+ cmd.stderr(unsafe { std::fs::File::from_raw_fd(stderr) });
+ self.fds.remove(&2);
+ }
}
}
}
@@ -250,10 +269,7 @@ impl Io {
impl Drop for Io {
fn drop(&mut self) {
for (_, file) in self.fds.drain() {
- let file = crate::mutex::unwrap(file);
- if file.as_raw_fd() <= 2 {
- let _ = file.into_raw_fd();
- }
+ File::maybe_drop(file);
}
}
}
@@ -265,15 +281,23 @@ pub enum File {
}
impl File {
- unsafe fn input(fd: std::os::unix::io::RawFd) -> Self {
+ pub unsafe fn input(fd: std::os::unix::io::RawFd) -> Self {
Self::In(async_std::io::BufReader::new(
async_std::fs::File::from_raw_fd(fd),
))
}
- unsafe fn output(fd: std::os::unix::io::RawFd) -> Self {
+ pub unsafe fn output(fd: std::os::unix::io::RawFd) -> Self {
Self::Out(async_std::fs::File::from_raw_fd(fd))
}
+
+ fn maybe_drop(file: crate::mutex::Mutex<Self>) {
+ if let Some(file) = crate::mutex::unwrap(file) {
+ if file.as_raw_fd() <= 2 {
+ let _ = file.into_raw_fd();
+ }
+ }
+ }
}
impl std::os::unix::io::AsRawFd for File {