A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

57 lines
1.7 KiB

use std::io::Result as IoResult;
use std::process::Command;
use std::process::Output;
pub trait CommandRunner {
fn run_with_args(&self, program: &str, args: &[&str]) -> IoResult<Output>;
}
#[derive(Debug)]
pub struct StdCommandRunner;
impl CommandRunner for StdCommandRunner {
fn run_with_args(&self, program: &str, args: &[&str]) -> IoResult<Output> {
// FIXME: logger
println!("{} {:?}", program, args);
let res = Command::new(program).args(args).output();
println!("{:?}", res);
res
}
}
#[derive(Debug)]
pub struct UserCommandRunner<'a, C> where C: 'a + CommandRunner {
command_runner: &'a C,
user_name: &'a str
}
impl<'a, C> UserCommandRunner<'a, C> where C: 'a + CommandRunner {
pub fn new(user_name: &'a str, command_runner: &'a C) -> UserCommandRunner<'a, C> {
UserCommandRunner {
command_runner: command_runner,
user_name: user_name
}
}
}
use std::os::unix::process::CommandExt;
use std::env;
use users::get_user_by_name;
impl<'a, C> CommandRunner for UserCommandRunner<'a, C> where C: 'a + CommandRunner {
fn run_with_args(&self, program: &str, args: &[&str]) -> IoResult<Output> {
let uid = get_user_by_name(self.user_name).unwrap().uid();
let old_home = env::var("HOME");
env::set_var("HOME", format!("/home/{}", self.user_name));
let old_dbus = env::var("DBUS_SESSION_BUS_ADDRESS");
env::set_var("DBUS_SESSION_BUS_ADDRESS", format!("unix:path=/run/user/{}/bus", uid));
let res = Command::new(program).uid(uid).gid(uid).args(args).output();
if let Ok(dbus) = old_dbus { env::set_var("DBUS_SESSION_BUS_ADDRESS", dbus); }
if let Ok(home) = old_home { env::set_var("HOME", home); }
res
}
}
#[cfg(test)]
mod test {
}