pub extern crate generic_array;
extern crate execute_command_tokens;
extern crate execute_command_macro;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, ErrorKind, Read, Write};
use std::process::{Command, Output, Stdio};
use std::sync::Once;
use generic_array::typenum::{IsGreaterOrEqual, True, U1, U256};
use generic_array::{ArrayLength, GenericArray};
use execute_command_tokens::command_tokens;
pub use execute_command_macro::{command, command_args};
pub trait Execute {
fn execute(&mut self) -> Result<Option<i32>, io::Error>;
fn execute_output(&mut self) -> Result<Output, io::Error>;
#[inline]
fn execute_check_exit_status_code(
&mut self,
expected_exit_status_code: i32,
) -> Result<(), io::Error> {
match self.execute()? {
Some(exit_status_code) if exit_status_code == expected_exit_status_code => Ok(()),
_ => Err(io::Error::new(ErrorKind::Other, "unexpected exit status")),
}
}
fn execute_input<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
) -> Result<Option<i32>, io::Error>;
fn execute_input_output<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
) -> Result<Output, io::Error>;
#[inline]
fn execute_input_reader(&mut self, reader: &mut dyn Read) -> Result<Option<i32>, io::Error> {
self.execute_input_reader2::<U256>(reader)
}
fn execute_input_reader2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
) -> Result<Option<i32>, io::Error>;
#[inline]
fn execute_input_reader_output(&mut self, reader: &mut dyn Read) -> Result<Output, io::Error> {
self.execute_input_reader_output2::<U256>(reader)
}
fn execute_input_reader_output2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
) -> Result<Output, io::Error>;
fn execute_multiple(&mut self, others: &mut [&mut Command]) -> Result<Option<i32>, io::Error>;
fn execute_multiple_output(&mut self, others: &mut [&mut Command])
-> Result<Output, io::Error>;
fn execute_multiple_input<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
others: &mut [&mut Command],
) -> Result<Option<i32>, io::Error>;
fn execute_multiple_input_output<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
others: &mut [&mut Command],
) -> Result<Output, io::Error>;
#[inline]
fn execute_multiple_input_reader(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Option<i32>, io::Error> {
self.execute_multiple_input_reader2::<U256>(reader, others)
}
fn execute_multiple_input_reader2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Option<i32>, io::Error>;
#[inline]
fn execute_multiple_input_reader_output(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Output, io::Error> {
self.execute_multiple_input_reader_output2::<U256>(reader, others)
}
fn execute_multiple_input_reader_output2<
N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>,
>(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Output, io::Error>;
}
impl Execute for Command {
#[inline]
fn execute(&mut self) -> Result<Option<i32>, io::Error> {
self.stdout(Stdio::null());
self.stderr(Stdio::null());
Ok(self.status()?.code())
}
#[inline]
fn execute_output(&mut self) -> Result<Output, io::Error> {
self.spawn()?.wait_with_output()
}
#[inline]
fn execute_input<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
) -> Result<Option<i32>, io::Error> {
self.stdin(Stdio::piped());
self.stdout(Stdio::null());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
child.stdin.as_mut().unwrap().write_all(data.as_ref())?;
Ok(child.wait()?.code())
}
#[inline]
fn execute_input_output<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
) -> Result<Output, io::Error> {
self.stdin(Stdio::piped());
let mut child = self.spawn()?;
child.stdin.as_mut().unwrap().write_all(data.as_ref())?;
child.wait_with_output()
}
#[inline]
fn execute_input_reader2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
) -> Result<Option<i32>, io::Error> {
self.stdin(Stdio::piped());
self.stdout(Stdio::null());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
{
let stdin = child.stdin.as_mut().unwrap();
let mut buffer: GenericArray<u8, N> = GenericArray::default();
loop {
match reader.read(&mut buffer) {
Ok(0) => break,
Ok(c) => stdin.write_all(&buffer[0..c])?,
Err(ref err) if err.kind() == ErrorKind::Interrupted => (),
Err(err) => return Err(err),
}
}
}
Ok(child.wait()?.code())
}
#[inline]
fn execute_input_reader_output2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
) -> Result<Output, io::Error> {
self.stdin(Stdio::piped());
let mut child = self.spawn()?;
{
let stdin = child.stdin.as_mut().unwrap();
let mut buffer: GenericArray<u8, N> = GenericArray::default();
loop {
match reader.read(&mut buffer) {
Ok(0) => break,
Ok(c) => stdin.write_all(&buffer[0..c])?,
Err(ref err) if err.kind() == ErrorKind::Interrupted => (),
Err(err) => return Err(err),
}
}
}
child.wait_with_output()
}
fn execute_multiple(&mut self, others: &mut [&mut Command]) -> Result<Option<i32>, io::Error> {
if others.is_empty() {
return self.execute();
}
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.stdout(Stdio::null());
last_other.stderr(Stdio::null());
Ok(last_other.status()?.code())
}
fn execute_multiple_output(
&mut self,
others: &mut [&mut Command],
) -> Result<Output, io::Error> {
if others.is_empty() {
return self.execute_output();
}
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.spawn()?.wait_with_output()
}
fn execute_multiple_input<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
others: &mut [&mut Command],
) -> Result<Option<i32>, io::Error> {
if others.is_empty() {
return self.execute_input(data);
}
self.stdin(Stdio::piped());
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
child.stdin.as_mut().unwrap().write_all(data.as_ref())?;
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.stdout(Stdio::null());
last_other.stderr(Stdio::null());
Ok(last_other.status()?.code())
}
fn execute_multiple_input_output<D: ?Sized + AsRef<[u8]>>(
&mut self,
data: &D,
others: &mut [&mut Command],
) -> Result<Output, io::Error> {
if others.is_empty() {
return self.execute_input_output(data);
}
self.stdin(Stdio::piped());
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
child.stdin.as_mut().unwrap().write_all(data.as_ref())?;
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.spawn()?.wait_with_output()
}
fn execute_multiple_input_reader2<N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>>(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Option<i32>, io::Error> {
if others.is_empty() {
return self.execute_input_reader2::<N>(reader);
}
self.stdin(Stdio::piped());
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
{
let stdin = child.stdin.as_mut().unwrap();
let mut buffer: GenericArray<u8, N> = GenericArray::default();
loop {
match reader.read(&mut buffer) {
Ok(0) => break,
Ok(c) => stdin.write_all(&buffer[0..c])?,
Err(ref err) if err.kind() == ErrorKind::Interrupted => (),
Err(err) => return Err(err),
}
}
}
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.stdout(Stdio::null());
last_other.stderr(Stdio::null());
Ok(last_other.status()?.code())
}
fn execute_multiple_input_reader_output2<
N: ArrayLength<u8> + IsGreaterOrEqual<U1, Output = True>,
>(
&mut self,
reader: &mut dyn Read,
others: &mut [&mut Command],
) -> Result<Output, io::Error> {
if others.is_empty() {
return self.execute_input_reader_output2::<N>(reader);
}
self.stdin(Stdio::piped());
self.stdout(Stdio::piped());
self.stderr(Stdio::null());
let mut child = self.spawn()?;
{
let stdin = child.stdin.as_mut().unwrap();
let mut buffer: GenericArray<u8, N> = GenericArray::default();
loop {
match reader.read(&mut buffer) {
Ok(0) => break,
Ok(c) => stdin.write_all(&buffer[0..c])?,
Err(ref err) if err.kind() == ErrorKind::Interrupted => (),
Err(err) => return Err(err),
}
}
}
let others_length_dec = others.len() - 1;
for other in others.iter_mut().take(others_length_dec) {
other.stdin(child.stdout.unwrap());
other.stdout(Stdio::piped());
other.stderr(Stdio::null());
child = other.spawn()?;
}
let last_other = &mut others[others_length_dec];
last_other.stdin(child.stdout.unwrap());
last_other.spawn()?.wait_with_output()
}
}
#[cfg(unix)]
#[inline]
pub fn shell<S: AsRef<OsStr>>(cmd: S) -> Command {
static START: Once = Once::new();
static mut SHELL: Option<OsString> = None;
let shell = unsafe {
START.call_once(|| {
SHELL = Some(env::var_os("SHELL").unwrap_or_else(|| OsString::from(String::from("sh"))))
});
SHELL.as_ref().unwrap()
};
let mut command = Command::new(shell);
command.arg("-c");
command.arg(cmd);
command
}
#[cfg(windows)]
#[inline]
pub fn shell<S: AsRef<OsStr>>(cmd: S) -> Command {
let mut command = Command::new("cmd.exe");
command.arg("/c");
command.arg(cmd);
command
}
#[inline]
pub fn command<S: AsRef<str>>(cmd: S) -> Command {
let tokens = command_tokens(cmd);
if tokens.is_empty() {
Command::new("")
} else {
let mut command = Command::new(&tokens[0]);
command.args(&tokens[1..]);
command
}
}