use std::error::Error; use std::fmt; use std::io::Error as IoError; use std::path::PathBuf; use std::str::from_utf8; use command_runner::CommandRunner; use symbols::Symbol; #[derive(Debug)] pub enum SystemdUserSessionError { ExecError(E), GenericError } impl Error for SystemdUserSessionError { fn description(&self) -> &str { match self { &SystemdUserSessionError::ExecError(ref e) => e.description(), &SystemdUserSessionError::GenericError => "Generic error" } } fn cause(&self) -> Option<&Error> { match self { &SystemdUserSessionError::ExecError(ref e) => Some(e), _ => None } } } impl fmt::Display for SystemdUserSessionError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "{}", self.description()) } } pub struct SystemdUserSession<'a> { user_name: &'a str, command_runner: &'a CommandRunner } impl<'a> SystemdUserSession<'a> { pub fn new(user_name: &'a str, command_runner: &'a CommandRunner) -> Self { SystemdUserSession { user_name: user_name, command_runner: command_runner } } } impl<'a> Symbol for SystemdUserSession<'a> { fn target_reached(&self) -> Result> { let mut path = PathBuf::from("/var/lib/systemd/linger"); path.push(self.user_name); Ok(path.exists()) // Could also do `loginctl show-user ${self.user_name} | grep -F 'Linger=yes` } fn execute(&self) -> Result<(), Box> { match self.command_runner.run_with_args("loginctl", &["enable-linger", self.user_name]) { Ok(output) => { println!("{:?} {:?}", from_utf8(&output.stdout).unwrap(), from_utf8(&output.stderr).unwrap() ); match output.status.code() { Some(0) => Ok(()), _ => Err(Box::new(SystemdUserSessionError::GenericError as SystemdUserSessionError)) } }, Err(e) => Err(Box::new(SystemdUserSessionError::ExecError(e))) } } } impl<'a> fmt::Display for SystemdUserSession<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ write!(f, "Systemd user session for {}", self.user_name) } }