pub mod io;
mod pipe;
mod runc;
use std::{
fmt::Debug,
io::{Read, Result, Write},
os::fd::AsRawFd,
};
use log::debug;
pub use pipe::Pipe;
pub use runc::{DefaultExecutor, Spawner};
use crate::Command;
pub trait Io: Debug + Send + Sync {
fn stdin(&self) -> Option<Box<dyn Write + Send + Sync>> {
None
}
fn stdout(&self) -> Option<Box<dyn Read + Send>> {
None
}
fn stderr(&self) -> Option<Box<dyn Read + Send>> {
None
}
fn set(&self, cmd: &mut Command) -> Result<()>;
fn close_after_start(&self);
}
#[derive(Debug)]
pub struct PipedIo {
pub stdin: Option<Pipe>,
pub stdout: Option<Pipe>,
pub stderr: Option<Pipe>,
}
impl Io for PipedIo {
fn stdin(&self) -> Option<Box<dyn Write + Send + Sync>> {
self.stdin.as_ref().and_then(|pipe| {
pipe.wr
.try_clone()
.map(|x| Box::new(x) as Box<dyn Write + Send + Sync>)
.ok()
})
}
fn stdout(&self) -> Option<Box<dyn Read + Send>> {
self.stdout.as_ref().and_then(|pipe| {
pipe.rd
.try_clone()
.map(|x| Box::new(x) as Box<dyn Read + Send>)
.ok()
})
}
fn stderr(&self) -> Option<Box<dyn Read + Send>> {
self.stderr.as_ref().and_then(|pipe| {
pipe.rd
.try_clone()
.map(|x| Box::new(x) as Box<dyn Read + Send>)
.ok()
})
}
fn set(&self, cmd: &mut Command) -> std::io::Result<()> {
if let Some(p) = self.stdin.as_ref() {
let pr = p.rd.try_clone()?;
cmd.stdin(pr);
}
if let Some(p) = self.stdout.as_ref() {
let pw = p.wr.try_clone()?;
cmd.stdout(pw);
}
if let Some(p) = self.stderr.as_ref() {
let pw = p.wr.try_clone()?;
cmd.stdout(pw);
}
Ok(())
}
fn close_after_start(&self) {
if let Some(p) = self.stdout.as_ref() {
nix::unistd::close(p.wr.as_raw_fd()).unwrap_or_else(|e| debug!("close stdout: {}", e));
}
if let Some(p) = self.stderr.as_ref() {
nix::unistd::close(p.wr.as_raw_fd()).unwrap_or_else(|e| debug!("close stderr: {}", e));
}
}
}