|
@ -1,4 +1,6 @@ |
|
|
use async_trait::async_trait;
|
|
|
use async_trait::async_trait;
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
use mockall::mock;
|
|
|
use std::error::Error;
|
|
|
use std::error::Error;
|
|
|
use std::ffi::OsStr;
|
|
|
use std::ffi::OsStr;
|
|
|
use std::io::Result as IoResult;
|
|
|
use std::io::Result as IoResult;
|
|
@ -33,30 +35,57 @@ pub fn get_output(output: Output) -> Result<Vec<u8>, Box<dyn Error>> { |
|
|
|
|
|
|
|
|
#[async_trait(?Send)]
|
|
|
#[async_trait(?Send)]
|
|
|
pub trait CommandRunner {
|
|
|
pub trait CommandRunner {
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], stdin: &[u8]) -> IoResult<Output>;
|
|
|
|
|
|
|
|
|
async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult<Output>;
|
|
|
|
|
|
|
|
|
async fn run_with_args(&self, program: &str, args: &[&OsStr]) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run_with_args<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> IoResult<Output> {
|
|
|
self.run(program, args, b"").await
|
|
|
self.run(program, args, b"").await
|
|
|
}
|
|
|
}
|
|
|
async fn get_output(&self, program: &str, args: &[&OsStr]) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
|
|
|
|
|
|
|
async fn get_output<'a>(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
program: &str,
|
|
|
|
|
|
args: &'a [&'a OsStr],
|
|
|
|
|
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
|
let output = self.run_with_args(program, args).await?;
|
|
|
let output = self.run_with_args(program, args).await?;
|
|
|
get_output(output)
|
|
|
get_output(output)
|
|
|
}
|
|
|
}
|
|
|
async fn run_successfully(&self, program: &str, args: &[&OsStr]) -> Result<(), Box<dyn Error>> {
|
|
|
|
|
|
|
|
|
async fn run_successfully<'a>(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
program: &str,
|
|
|
|
|
|
args: &'a [&'a OsStr],
|
|
|
|
|
|
) -> Result<(), Box<dyn Error>> {
|
|
|
is_success(self.run(program, args, b"").await)?;
|
|
|
is_success(self.run(program, args, b"").await)?;
|
|
|
Ok(())
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
async fn get_stderr(&self, program: &str, args: &[&OsStr]) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
|
|
|
|
|
|
|
async fn get_stderr<'a>(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
program: &str,
|
|
|
|
|
|
args: &'a [&'a OsStr],
|
|
|
|
|
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
|
Ok(is_success(self.run_with_args(program, args).await)?.stderr)
|
|
|
Ok(is_success(self.run_with_args(program, args).await)?.stderr)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mock! {
|
|
|
|
|
|
pub CommandRunner {
|
|
|
|
|
|
}
|
|
|
|
|
|
#[async_trait(?Send)]
|
|
|
|
|
|
impl CommandRunner for CommandRunner {
|
|
|
|
|
|
async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult<Output>;
|
|
|
|
|
|
|
|
|
|
|
|
async fn run_with_args<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> IoResult<Output>;
|
|
|
|
|
|
async fn get_output<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result<Vec<u8>, Box<dyn Error>>;
|
|
|
|
|
|
async fn run_successfully<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result<(), Box<dyn Error>>;
|
|
|
|
|
|
async fn get_stderr<'a>(&self, program: &str, args: &'a [&'a OsStr]) -> Result<Vec<u8>, Box<dyn Error>>;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct StdCommandRunner;
|
|
|
pub struct StdCommandRunner;
|
|
|
|
|
|
|
|
|
#[async_trait(?Send)]
|
|
|
#[async_trait(?Send)]
|
|
|
impl CommandRunner for StdCommandRunner {
|
|
|
impl CommandRunner for StdCommandRunner {
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], input: &[u8]) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult<Output> {
|
|
|
//println!("{} {:?}", program, args);
|
|
|
//println!("{} {:?}", program, args);
|
|
|
let mut child = Command::new(program)
|
|
|
let mut child = Command::new(program)
|
|
|
.args(args)
|
|
|
.args(args)
|
|
@ -114,7 +143,7 @@ impl Drop for TempSetEnv<'_> { |
|
|
|
|
|
|
|
|
#[async_trait(?Send)]
|
|
|
#[async_trait(?Send)]
|
|
|
impl<U: AsRef<str>> CommandRunner for SetuidCommandRunner<U> {
|
|
|
impl<U: AsRef<str>> CommandRunner for SetuidCommandRunner<U> {
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], input: &[u8]) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run<'a>(&self, program: &str, args: &'a [&'a OsStr], input: &[u8]) -> IoResult<Output> {
|
|
|
let uid = get_user_by_name(self.user_name.as_ref())
|
|
|
let uid = get_user_by_name(self.user_name.as_ref())
|
|
|
.expect("User does not exist")
|
|
|
.expect("User does not exist")
|
|
|
.uid();
|
|
|
.uid();
|
|
|