use std::borrow::{ Borrow, Cow }; use std::error::Error; use std::fmt; use std::path::PathBuf; use command_runner::CommandRunner; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; #[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: Cow<'a, str>, command_runner: &'a CommandRunner } impl<'a> SystemdUserSession<'a> { pub fn new(user_name: Cow<'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.borrow() as &str); Ok(path.exists()) // Could also do `loginctl show-user ${self.user_name} | grep -F 'Linger=yes` } fn execute(&self) -> Result<(), Box> { self.command_runner.run_successfully("loginctl", &["enable-linger", self.user_name.borrow()]) } fn as_action<'b>(&'b self, runner: &'b SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } fn into_action<'b>(self: Box, runner: &'b SymbolRunner) -> Box where Self: 'b { Box::new(OwnedSymbolAction::new(runner, *self)) } } 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) } }