1909e4d10SGnoCiYeH use lazy_static::lazy_static; 2909e4d10SGnoCiYeH use std::fs::File; 3909e4d10SGnoCiYeH use std::os::fd::FromRawFd; 4*dfd3fd98S裕依2439 use std::sync::{Arc, Mutex}; 5909e4d10SGnoCiYeH 6909e4d10SGnoCiYeH use crate::error::runtime_error::RuntimeError; 7909e4d10SGnoCiYeH use crate::error::runtime_error::RuntimeErrorType; 8909e4d10SGnoCiYeH use crate::error::ErrorFormat; 9909e4d10SGnoCiYeH use crate::parse::parse_util::UnitParseUtil; 10*dfd3fd98S裕依2439 use crate::systemctl::ctl_parser::{CommandOperation, Pattern}; 11909e4d10SGnoCiYeH use crate::systemctl::ctl_path; 12909e4d10SGnoCiYeH use crate::systemctl::listener::Command; 13909e4d10SGnoCiYeH use crate::unit::Unit; 14909e4d10SGnoCiYeH use crate::unit::UnitState; 15909e4d10SGnoCiYeH 16909e4d10SGnoCiYeH use super::{UnitManager, ID_TO_UNIT_MAP}; 17909e4d10SGnoCiYeH pub struct CtlManager; 18909e4d10SGnoCiYeH 19909e4d10SGnoCiYeH lazy_static! { 20909e4d10SGnoCiYeH static ref CTL_WRITER: Mutex<Arc<File>> = { 21909e4d10SGnoCiYeH let file = CtlManager::init_ctl_writer(); 22909e4d10SGnoCiYeH Mutex::new(Arc::new(file)) 23909e4d10SGnoCiYeH }; 24909e4d10SGnoCiYeH } 25909e4d10SGnoCiYeH 26909e4d10SGnoCiYeH impl CtlManager { exec_ctl(cmd: Command) -> Result<(), RuntimeError>27909e4d10SGnoCiYeH pub fn exec_ctl(cmd: Command) -> Result<(), RuntimeError> { 28909e4d10SGnoCiYeH // TODO:目前假设一个时刻只有一个进程使用systemdctl,后续应该使用DBus等更灵活的进程通信方式 29909e4d10SGnoCiYeH match cmd.operation { 30*dfd3fd98S裕依2439 CommandOperation::ListUnits => Self::list_unit(cmd.patterns), 31*dfd3fd98S裕依2439 CommandOperation::Start => Self::start(cmd.args.unwrap()), 32*dfd3fd98S裕依2439 CommandOperation::Restart => Self::restart(cmd.args.unwrap(), false), 33*dfd3fd98S裕依2439 CommandOperation::Stop => Self::stop(cmd.args.unwrap()), 34*dfd3fd98S裕依2439 CommandOperation::Reboot => Ok(Self::reboot()), 35*dfd3fd98S裕依2439 CommandOperation::ListSockets => todo!(), 36*dfd3fd98S裕依2439 CommandOperation::ListTimers => todo!(), 37*dfd3fd98S裕依2439 CommandOperation::Reload => todo!(), 38*dfd3fd98S裕依2439 CommandOperation::TryRestart => Self::restart(cmd.args.unwrap(), true), 39*dfd3fd98S裕依2439 CommandOperation::ReloadOrRestart => todo!(), 40*dfd3fd98S裕依2439 CommandOperation::ReloadOrTryRestart => todo!(), 41*dfd3fd98S裕依2439 CommandOperation::Isolate => todo!(), 42*dfd3fd98S裕依2439 CommandOperation::Kill => todo!(), 43*dfd3fd98S裕依2439 CommandOperation::IsActive => { 44909e4d10SGnoCiYeH let mut patterns = cmd.patterns.clone(); 45909e4d10SGnoCiYeH patterns.push(Pattern::State(UnitState::Active)); 46909e4d10SGnoCiYeH Self::list_unit(patterns) 47909e4d10SGnoCiYeH } 48*dfd3fd98S裕依2439 CommandOperation::IsFailed => { 49909e4d10SGnoCiYeH let mut patterns = cmd.patterns.clone(); 50909e4d10SGnoCiYeH patterns.push(Pattern::State(UnitState::Failed)); 51909e4d10SGnoCiYeH Self::list_unit(patterns) 52909e4d10SGnoCiYeH } 53*dfd3fd98S裕依2439 CommandOperation::Status => todo!(), 54*dfd3fd98S裕依2439 CommandOperation::Show => todo!(), 55*dfd3fd98S裕依2439 CommandOperation::Cat => todo!(), 56*dfd3fd98S裕依2439 CommandOperation::SetProperty => todo!(), 57*dfd3fd98S裕依2439 CommandOperation::Help => todo!(), 58*dfd3fd98S裕依2439 CommandOperation::ResetFailed => todo!(), 59*dfd3fd98S裕依2439 CommandOperation::ListDependencies => todo!(), 60*dfd3fd98S裕依2439 CommandOperation::ListUnitFiles => todo!(), 61*dfd3fd98S裕依2439 CommandOperation::Enable => todo!(), 62*dfd3fd98S裕依2439 CommandOperation::Disable => todo!(), 63*dfd3fd98S裕依2439 CommandOperation::Reenable => todo!(), 64*dfd3fd98S裕依2439 CommandOperation::Preset => todo!(), 65*dfd3fd98S裕依2439 CommandOperation::PresetAll => todo!(), 66*dfd3fd98S裕依2439 CommandOperation::IsEnabled => todo!(), 67*dfd3fd98S裕依2439 CommandOperation::Mask => todo!(), 68*dfd3fd98S裕依2439 CommandOperation::UnMask => todo!(), 69*dfd3fd98S裕依2439 CommandOperation::Link => todo!(), 70*dfd3fd98S裕依2439 CommandOperation::AddWants => todo!(), 71*dfd3fd98S裕依2439 CommandOperation::AddRequires => todo!(), 72*dfd3fd98S裕依2439 CommandOperation::Edit => todo!(), 73*dfd3fd98S裕依2439 CommandOperation::GetDefault => todo!(), 74*dfd3fd98S裕依2439 CommandOperation::SetDefault => todo!(), 75*dfd3fd98S裕依2439 CommandOperation::ListMachines => todo!(), 76*dfd3fd98S裕依2439 CommandOperation::ListJobs => todo!(), 77*dfd3fd98S裕依2439 CommandOperation::Cancel => todo!(), 78*dfd3fd98S裕依2439 CommandOperation::Snapshot => todo!(), 79*dfd3fd98S裕依2439 CommandOperation::Delete => todo!(), 80*dfd3fd98S裕依2439 CommandOperation::ShowEnvironment => todo!(), 81*dfd3fd98S裕依2439 CommandOperation::SetEnvironment => todo!(), 82*dfd3fd98S裕依2439 CommandOperation::UnsetEnvironment => todo!(), 83*dfd3fd98S裕依2439 CommandOperation::ImportEnvironment => todo!(), 84*dfd3fd98S裕依2439 CommandOperation::DeamonReload => todo!(), 85*dfd3fd98S裕依2439 CommandOperation::DeamonReexec => todo!(), 86*dfd3fd98S裕依2439 CommandOperation::IsSystemRunning => todo!(), 87*dfd3fd98S裕依2439 CommandOperation::Default => todo!(), 88*dfd3fd98S裕依2439 CommandOperation::Rescue => todo!(), 89*dfd3fd98S裕依2439 CommandOperation::Emergency => todo!(), 90*dfd3fd98S裕依2439 CommandOperation::Halt => todo!(), 91*dfd3fd98S裕依2439 CommandOperation::Poweroff => todo!(), 92*dfd3fd98S裕依2439 CommandOperation::Kexec => todo!(), 93*dfd3fd98S裕依2439 CommandOperation::Exit => todo!(), 94*dfd3fd98S裕依2439 CommandOperation::SwitchRoot => todo!(), 95*dfd3fd98S裕依2439 CommandOperation::Suspend => todo!(), 96*dfd3fd98S裕依2439 CommandOperation::Hibernate => todo!(), 97*dfd3fd98S裕依2439 CommandOperation::HybridSleep => todo!(), 98*dfd3fd98S裕依2439 CommandOperation::UnSupported => todo!(), 99*dfd3fd98S裕依2439 CommandOperation::None => { 100909e4d10SGnoCiYeH println!("No such command!"); 101909e4d10SGnoCiYeH return Err(RuntimeError::new(RuntimeErrorType::InvalidInput)); 102909e4d10SGnoCiYeH } 103909e4d10SGnoCiYeH } 104909e4d10SGnoCiYeH } 105909e4d10SGnoCiYeH list_unit(pattern: Vec<Pattern>) -> Result<(), RuntimeError>106909e4d10SGnoCiYeH pub fn list_unit(pattern: Vec<Pattern>) -> Result<(), RuntimeError> { 107909e4d10SGnoCiYeH let units = Self::filter_units(pattern)?; 108909e4d10SGnoCiYeH 109909e4d10SGnoCiYeH let mut res = "UNIT\t\t\t\tLOAD\t\tACTIVE\t\tSUB\t\tDESCRIPTION".to_string(); 110909e4d10SGnoCiYeH res.push_str("\n----------------------------------------------------------------------------------------------"); 111909e4d10SGnoCiYeH for unit in units { 112909e4d10SGnoCiYeH res = format!("{}\n{}", res, unit.lock().unwrap().unit_base().unit_info()); 113909e4d10SGnoCiYeH } 114909e4d10SGnoCiYeH 115909e4d10SGnoCiYeH // if let Err(err) = CTL_WRITER.lock().unwrap().write_all(res.as_bytes()) { 116909e4d10SGnoCiYeH // eprintln!("write ctl error :{}", err); 117909e4d10SGnoCiYeH // } 118909e4d10SGnoCiYeH println!("{}", res); 119909e4d10SGnoCiYeH Ok(()) 120909e4d10SGnoCiYeH } 121909e4d10SGnoCiYeH stop(names: Vec<String>) -> Result<(), RuntimeError>122909e4d10SGnoCiYeH pub fn stop(names: Vec<String>) -> Result<(), RuntimeError> { 123909e4d10SGnoCiYeH // TODO:打日志 124909e4d10SGnoCiYeH for name in names { 125909e4d10SGnoCiYeH match UnitManager::get_unit_with_name(&name) { 126909e4d10SGnoCiYeH Some(unit) => { 127909e4d10SGnoCiYeH unit.lock().unwrap().exit(); 128909e4d10SGnoCiYeH } 129909e4d10SGnoCiYeH None => { 130909e4d10SGnoCiYeH eprintln!("{} is not a unit", name); 131909e4d10SGnoCiYeH return Err(RuntimeError::new(RuntimeErrorType::FileNotFound)); 132909e4d10SGnoCiYeH } 133909e4d10SGnoCiYeH } 134909e4d10SGnoCiYeH } 135909e4d10SGnoCiYeH Ok(()) 136909e4d10SGnoCiYeH } 137909e4d10SGnoCiYeH start(names: Vec<String>) -> Result<(), RuntimeError>138909e4d10SGnoCiYeH pub fn start(names: Vec<String>) -> Result<(), RuntimeError> { 139909e4d10SGnoCiYeH // TODO:打日志 140909e4d10SGnoCiYeH for name in names { 141909e4d10SGnoCiYeH match UnitManager::get_unit_with_name(&name) { 142909e4d10SGnoCiYeH Some(unit) => unit.lock().unwrap().run()?, 143909e4d10SGnoCiYeH None => match UnitParseUtil::parse_unit_no_type(&name) { 144909e4d10SGnoCiYeH Ok(i) => { 145909e4d10SGnoCiYeH let unit = UnitManager::get_unit_with_id(&i).unwrap(); 146909e4d10SGnoCiYeH let mut unit = unit.lock().unwrap(); 147909e4d10SGnoCiYeH unit.run()?; 148909e4d10SGnoCiYeH } 149909e4d10SGnoCiYeH Err(err) => { 150909e4d10SGnoCiYeH eprintln!("parse unit {} error :{}", name, err.error_format()); 151909e4d10SGnoCiYeH } 152909e4d10SGnoCiYeH }, 153909e4d10SGnoCiYeH } 154909e4d10SGnoCiYeH } 155909e4d10SGnoCiYeH Ok(()) 156909e4d10SGnoCiYeH } 157909e4d10SGnoCiYeH reboot()158909e4d10SGnoCiYeH pub fn reboot() { 159*dfd3fd98S裕依2439 unsafe { libc::syscall(libc::SYS_reboot, 0, 0, 0, 0, 0, 0) }; 160909e4d10SGnoCiYeH } 161909e4d10SGnoCiYeH restart(names: Vec<String>, is_try: bool) -> Result<(), RuntimeError>162909e4d10SGnoCiYeH pub fn restart(names: Vec<String>, is_try: bool) -> Result<(), RuntimeError> { 163909e4d10SGnoCiYeH // TODO:打日志 164909e4d10SGnoCiYeH for name in names { 165909e4d10SGnoCiYeH match UnitManager::get_unit_with_name(&name) { 166909e4d10SGnoCiYeH Some(unit) => { 167909e4d10SGnoCiYeH let mut unit = unit.lock().unwrap(); 168909e4d10SGnoCiYeH if is_try && *unit.unit_base().state() == UnitState::Active { 169909e4d10SGnoCiYeH unit.restart()?; 170909e4d10SGnoCiYeH } else { 171909e4d10SGnoCiYeH unit.restart()?; 172909e4d10SGnoCiYeH } 173909e4d10SGnoCiYeH } 174909e4d10SGnoCiYeH None => match UnitParseUtil::parse_unit_no_type(&name) { 175909e4d10SGnoCiYeH Ok(i) => { 176909e4d10SGnoCiYeH let unit = UnitManager::get_unit_with_id(&i).unwrap(); 177909e4d10SGnoCiYeH unit.lock().unwrap().run()?; 178909e4d10SGnoCiYeH } 179909e4d10SGnoCiYeH Err(err) => { 180909e4d10SGnoCiYeH eprintln!("parse unit {} error :{}", name, err.error_format()); 181909e4d10SGnoCiYeH return Err(RuntimeError::new(RuntimeErrorType::InvalidFileFormat)); 182909e4d10SGnoCiYeH } 183909e4d10SGnoCiYeH }, 184909e4d10SGnoCiYeH } 185909e4d10SGnoCiYeH } 186909e4d10SGnoCiYeH Ok(()) 187909e4d10SGnoCiYeH } 188909e4d10SGnoCiYeH init_ctl_writer() -> File189909e4d10SGnoCiYeH pub fn init_ctl_writer() -> File { 190909e4d10SGnoCiYeH let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_WRONLY) }; 191909e4d10SGnoCiYeH if fd < 0 { 192909e4d10SGnoCiYeH panic!("open ctl pipe error"); 193909e4d10SGnoCiYeH } 194909e4d10SGnoCiYeH unsafe { File::from_raw_fd(fd) } 195909e4d10SGnoCiYeH } 196909e4d10SGnoCiYeH filter_units(patterns: Vec<Pattern>) -> Result<Vec<Arc<Mutex<dyn Unit>>>, RuntimeError>197909e4d10SGnoCiYeH pub fn filter_units(patterns: Vec<Pattern>) -> Result<Vec<Arc<Mutex<dyn Unit>>>, RuntimeError> { 198909e4d10SGnoCiYeH let reader = ID_TO_UNIT_MAP.read().unwrap(); 199909e4d10SGnoCiYeH 200909e4d10SGnoCiYeH // TODO: 这里可以优化 201909e4d10SGnoCiYeH let bindings = reader.values().collect::<Vec<_>>(); 202909e4d10SGnoCiYeH let mut units = Vec::new(); 203909e4d10SGnoCiYeH for unit in bindings { 204909e4d10SGnoCiYeH units.push(unit.clone()); 205909e4d10SGnoCiYeH } 206909e4d10SGnoCiYeH for pat in patterns { 207909e4d10SGnoCiYeH match pat { 208909e4d10SGnoCiYeH Pattern::Type(t) => { 209909e4d10SGnoCiYeH units = units 210909e4d10SGnoCiYeH .into_iter() 211909e4d10SGnoCiYeH .filter(|x| x.lock().unwrap().unit_type() == t) 212909e4d10SGnoCiYeH .collect::<Vec<_>>() 213909e4d10SGnoCiYeH } 214909e4d10SGnoCiYeH Pattern::State(s) => { 215909e4d10SGnoCiYeH units = units 216909e4d10SGnoCiYeH .into_iter() 217909e4d10SGnoCiYeH .filter(|x| *x.lock().unwrap().unit_base().state() == s) 218909e4d10SGnoCiYeH .collect::<Vec<_>>() 219909e4d10SGnoCiYeH } 220909e4d10SGnoCiYeH Pattern::None => {} 221909e4d10SGnoCiYeH _ => { 222909e4d10SGnoCiYeH return Err(RuntimeError::new(RuntimeErrorType::InvalidInput)); 223909e4d10SGnoCiYeH } 224909e4d10SGnoCiYeH } 225909e4d10SGnoCiYeH } 226909e4d10SGnoCiYeH Ok(units) 227909e4d10SGnoCiYeH } 228909e4d10SGnoCiYeH } 229