diff options
Diffstat (limited to 'src/prepared_command.rs')
-rw-r--r-- | src/prepared_command.rs | 100 |
1 files changed, 0 insertions, 100 deletions
diff --git a/src/prepared_command.rs b/src/prepared_command.rs deleted file mode 100644 index 8297095..0000000 --- a/src/prepared_command.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::{ - ffi::{CString, OsStr}, - io::{Error, ErrorKind, Result}, - iter, - os::unix::{ffi::*, io::RawFd}, - ptr, -}; - -use libc::{c_char, c_void}; -use nix::{fcntl::OFlag, sys::wait, unistd}; - -use crate::util::ToIOResult; - -#[derive(Clone, Debug)] -pub struct PreparedCommandBuilder { - program: CString, - args: Vec<CString>, -} - -#[derive(Debug)] -pub struct PreparedCommand { - child: unistd::Pid, - pipew: RawFd, -} - -impl Drop for PreparedCommand { - fn drop(&mut self) { - assert!(unistd::close(self.pipew).is_ok()); - } -} - -fn os2c<S: AsRef<OsStr>>(s: S) -> CString { - CString::new(s.as_ref().as_bytes()).unwrap() -} - -impl PreparedCommandBuilder { - pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self { - self.args.push(os2c(arg)); - self - } - - pub fn prepare(&mut self) -> Result<PreparedCommand> { - let exe_p = self.program.as_ptr(); - - let argv: Vec<*const c_char> = iter::once(exe_p) - .chain(self.args.iter().map(|arg| arg.as_ptr())) - .chain(iter::once(ptr::null())) - .collect(); - - let argv_p = argv.as_ptr(); - - let (piper, pipew) = unistd::pipe2(OFlag::O_CLOEXEC).to_io_result()?; - - unsafe { - match unistd::fork().to_io_result()? { - unistd::ForkResult::Parent { child } => { - let cmd = PreparedCommand { child, pipew }; - assert!(unistd::close(piper).is_ok()); - return Ok(cmd); - } - unistd::ForkResult::Child => {} - } - - // Child process - only async-signal-safe calls allowed - - if libc::close(pipew) != 0 { - libc::_exit(126); - } - - // Wait for run trigger - let mut buf = [0u8; 1]; - if libc::read(piper, buf.as_mut_ptr() as *mut c_void, buf.len()) != 1 { - // PreparedCommand was dropped, or controlling process exited - libc::_exit(126); - } - - libc::execvp(exe_p, argv_p); - - // exec failed - libc::_exit(127); - } - } -} - -impl PreparedCommand { - pub fn new<S: AsRef<OsStr>>(program: S) -> PreparedCommandBuilder { - PreparedCommandBuilder { - program: os2c(program), - args: Vec::new(), - } - } - - pub fn run(self) -> Result<wait::WaitStatus> { - if unistd::write(self.pipew, &[0]).to_io_result()? != 1 { - return Err(Error::new(ErrorKind::Other, "command trigger write failed")); - } - - wait::waitpid(Some(self.child), None).to_io_result() - } -} |