xref: /DragonReach/src/manager/ctl_manager/mod.rs (revision dfd3fd9812f3584f9392934d1254e24d17661b2d)
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