|
@ -33,17 +33,17 @@ 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: &str) -> IoResult<Output>;
|
|
|
|
|
|
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], stdin: &[u8]) -> IoResult<Output>;
|
|
|
|
|
|
|
|
|
async fn run_with_args(&self, program: &str, args: &[&OsStr]) -> IoResult<Output> {
|
|
|
async fn run_with_args(&self, program: &str, args: &[&OsStr]) -> IoResult<Output> {
|
|
|
self.run(program, args, "").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(&self, program: &str, args: &[&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(&self, program: &str, args: &[&OsStr]) -> Result<(), Box<dyn Error>> {
|
|
|
is_success(self.run(program, args, "").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(&self, program: &str, args: &[&OsStr]) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
@ -56,7 +56,7 @@ 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: &str) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run(&self, program: &str, args: &[&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)
|
|
@ -67,7 +67,7 @@ impl CommandRunner for StdCommandRunner { |
|
|
.expect("Failed to spawn child process");
|
|
|
.expect("Failed to spawn child process");
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
stdin
|
|
|
stdin
|
|
|
.write_all(input.as_bytes())
|
|
|
|
|
|
|
|
|
.write_all(input)
|
|
|
.await
|
|
|
.await
|
|
|
.expect("Failed to write to stdin");
|
|
|
.expect("Failed to write to stdin");
|
|
|
let res = child.wait_with_output().await;
|
|
|
let res = child.wait_with_output().await;
|
|
@ -122,7 +122,7 @@ impl Drop for TempSetEnv<'_> { |
|
|
|
|
|
|
|
|
#[async_trait(?Send)]
|
|
|
#[async_trait(?Send)]
|
|
|
impl<U: AsRef<str>, C: CommandRunner> CommandRunner for SetuidCommandRunner<'_, U, C> {
|
|
|
impl<U: AsRef<str>, C: CommandRunner> CommandRunner for SetuidCommandRunner<'_, U, C> {
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], input: &str) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run(&self, program: &str, args: &[&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();
|
|
@ -140,7 +140,7 @@ impl<U: AsRef<str>, C: CommandRunner> CommandRunner for SetuidCommandRunner<'_, |
|
|
.expect("Failed to spawn child process");
|
|
|
.expect("Failed to spawn child process");
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
stdin
|
|
|
stdin
|
|
|
.write_all(input.as_bytes())
|
|
|
|
|
|
|
|
|
.write_all(input)
|
|
|
.await
|
|
|
.await
|
|
|
.expect("Failed to write to stdin");
|
|
|
.expect("Failed to write to stdin");
|
|
|
let res = child.wait_with_output().await;
|
|
|
let res = child.wait_with_output().await;
|
|
@ -179,7 +179,7 @@ impl<'a, C> CommandRunner for SuCommandRunner<'a, C> |
|
|
where
|
|
|
where
|
|
|
C: 'a + CommandRunner,
|
|
|
C: 'a + CommandRunner,
|
|
|
{
|
|
|
{
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], input: &str) -> IoResult<Output> {
|
|
|
|
|
|
|
|
|
async fn run(&self, program: &str, args: &[&OsStr], input: &[u8]) -> IoResult<Output> {
|
|
|
let raw_new_args = [self.user_name, "-s", "/usr/bin/env", "--", program];
|
|
|
let raw_new_args = [self.user_name, "-s", "/usr/bin/env", "--", program];
|
|
|
let mut new_args: Vec<&OsStr> = raw_new_args.iter().map(AsRef::as_ref).collect();
|
|
|
let mut new_args: Vec<&OsStr> = raw_new_args.iter().map(AsRef::as_ref).collect();
|
|
|
new_args.extend_from_slice(args);
|
|
|
new_args.extend_from_slice(args);
|
|
@ -201,8 +201,8 @@ mod test { |
|
|
run(async {
|
|
|
run(async {
|
|
|
let args = args!["1"];
|
|
|
let args = args!["1"];
|
|
|
let start = Instant::now();
|
|
|
let start = Instant::now();
|
|
|
let res = c.run("sleep", args, "").fuse();
|
|
|
|
|
|
let ps = c.run("ps", args![], "").fuse();
|
|
|
|
|
|
|
|
|
let res = c.run("sleep", args, b"").fuse();
|
|
|
|
|
|
let ps = c.run("ps", args![], b"").fuse();
|
|
|
futures_util::pin_mut!(res, ps);
|
|
|
futures_util::pin_mut!(res, ps);
|
|
|
loop {
|
|
|
loop {
|
|
|
futures_util::select! {
|
|
|
futures_util::select! {
|
|
|