summaryrefslogtreecommitdiffstats
path: root/src/prepared_command.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/prepared_command.rs')
-rw-r--r--src/prepared_command.rs100
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()
- }
-}