Quellcode durchsuchen

几个简单的systemctl命令

GnoCiYeH vor 1 Jahr
Ursprung
Commit
50280a2da3

+ 1 - 0
.vscode/settings.json

@@ -1,6 +1,7 @@
 {
     "rust-analyzer.linkedProjects": [
         "./Cargo.toml",
+        "./systemctl/Cargo.toml"
     ],
     "rust-analyzer.check.overrideCommand": [
         "make",

+ 11 - 1
Makefile

@@ -9,6 +9,7 @@ TMP_INSTALL_DIR=$(OUTPUT_DIR)/tmp_install
 all: build
 
 build:
+	@$(MAKE) -C ./systemctl build
 	cargo -Z build-std=core,alloc,compiler_builtins build --target ./x86_64-unknown-dragonos.json --release
 
 install:
@@ -16,25 +17,34 @@ install:
 	mkdir -p $(REACH_ETC_DIR)
 	mkdir -p $(REACH_ETC_DIR)/system/
 	mkdir -p $(REACH_BIN_DIR)
+	mkdir -p $(REACH_ETC_DIR)/ipc/
 
 	cp ./parse_test/shell.service $(REACH_ETC_DIR)/system/shell.service
 
 	cargo -Z build-std=core,alloc,compiler_builtins install --target $(TARGET) --path .  --root $(TMP_INSTALL_DIR)
 	mv $(TMP_INSTALL_DIR)/bin/DragonReach $(REACH_BIN_DIR)/DragonReach
+	
+	cargo -Z build-std=core,alloc,compiler_builtins install --target $(TARGET) --path ./systemctl  --root $(TMP_INSTALL_DIR)
+	mv $(TMP_INSTALL_DIR)/bin/systemctl $(REACH_BIN_DIR)/systemctl
+	
 	rm -rf $(TMP_INSTALL_DIR)
 
 build-linux:
+	@$(MAKE) -C ./systemctl build-linux
 	cargo -Z build-std=core,alloc,compiler_builtins build --target x86_64-unknown-linux-gnu
 
 clean:
 	cargo clean
-
+	@$(MAKE) -C ./systemctl clean
 
 fmt:
 	cargo fmt
+	@$(MAKE) -C ./systemctl fmt
 
 fmt-check:
 	cargo fmt --check
+	@$(MAKE) -C ./systemctl fmt-check
 
 check:
 	cargo -Z build-std=core,alloc,compiler_builtins check --workspace --message-format=json --target ./x86_64-unknown-dragonos.json
+	@$(MAKE) -C ./systemctl check

+ 2 - 2
parse_test/shell.service

@@ -4,5 +4,5 @@ Description=Shell
 [Service]
 Type=simple
 ExecStart=/bin/shell.elf
-Restart=always
-RestartSec=5000
+#Restart=always
+#RestartSec=500000

+ 28 - 1
src/executor/mod.rs

@@ -4,6 +4,7 @@ pub mod service_executor;
 use crate::{
     error::runtime_error::{RuntimeError, RuntimeErrorType},
     manager::UnitManager,
+    unit::UnitState,
 };
 
 #[allow(dead_code)]
@@ -39,8 +40,26 @@ impl Executor {
     pub fn exec(unit_id: usize) -> Result<(), RuntimeError> {
         // TODO: 添加超时检测,这个工作应该在线程执行
 
+        {
+            // 设置Unit状态为正在启动
+            // TODO: 目前单线程工作这样设置是无意义的
+            UnitManager::get_unit_with_id(&unit_id)
+                .unwrap()
+                .lock()
+                .unwrap()
+                .unit_base_mut()
+                .set_state(UnitState::Activating);
+        }
         match Self::exec_(unit_id) {
-            Ok(_) => Ok(()),
+            Ok(_) => {
+                UnitManager::get_unit_with_id(&unit_id)
+                .unwrap()
+                .lock()
+                .unwrap()
+                .unit_base_mut()
+                .set_state(UnitState::Active);
+                Ok(())
+            },
             Err(e) => {
                 let mutex = UnitManager::get_unit_with_id(&unit_id).unwrap();
                 let mut unit = mutex.lock().unwrap();
@@ -51,6 +70,7 @@ impl Executor {
                     let _ = Executor::exec(*id);
                 }
 
+                unit.unit_base_mut().set_state(UnitState::Failed);
                 unit.after_exit(ExitStatus::Failure);
                 return Err(e);
             }
@@ -118,4 +138,11 @@ impl Executor {
         unit.run()?;
         return Ok(());
     }
+
+    pub fn restart(id: usize) -> Result<(), RuntimeError> {
+        if let Some(unit) = UnitManager::get_unit_with_id(&id) {
+            unit.lock().unwrap().restart()?;
+        }
+        Ok(())
+    }
 }

+ 44 - 33
src/executor/service_executor/mod.rs

@@ -12,7 +12,7 @@ use std::process::Command;
 use std::process::Stdio;
 use std::time::Duration;
 use std::vec::Vec;
-use std::{eprint, eprintln, print, println};
+use std::{eprint, eprintln};
 
 use super::{Executor, ExitStatus};
 
@@ -39,7 +39,7 @@ impl ServiceExecutor {
             // 如果有冲突项enable的时候,该unit不能启动
             let mutex = UnitManager::get_unit_with_id(u).unwrap();
             let unit = mutex.lock().unwrap();
-            if *unit.unit_base().state() == UnitState::Enabled {
+            if *unit.unit_base().state() == UnitState::Active {
                 eprintln!(
                     "{}: Service startup failed: conflict unit",
                     unit.unit_base().unit_part().description()
@@ -69,9 +69,9 @@ impl ServiceExecutor {
 
         match proc {
             Ok(p) => {
-                println!("Service running...");
+                // TODO: 打日志
                 //修改service状态
-                service.mut_unit_base().set_state(UnitState::Enabled);
+                service.unit_base_mut().set_state(UnitState::Active);
                 //启动成功后将Child加入全局管理的进程表
                 UnitManager::push_running(service.unit_id(), p);
                 //执行启动后命令
@@ -170,35 +170,12 @@ impl ServiceExecutor {
 
         // 关闭和此服务绑定的项目
         for bind in service.unit_base().unit_part().be_binded_by() {
-            UnitManager::kill_running(*bind);
+            UnitManager::try_kill_running(*bind);
         }
 
         //判断是否需要restart,需要则再次启动服务
         if service.service_part().restart().is_restart(&exit_status) {
-            let ns = service.service_part().restart_sec();
-            let binds = service.unit_base().unit_part().be_binded_by();
-            let binds = Vec::from(binds);
-            let id = service.unit_id();
-            if ns > 0 {
-                let cmds = service.service_part().exec_reload().clone();
-                TimerManager::push_timer(
-                    Duration::from_nanos(ns),
-                    move || {
-                        for cmd in &cmds {
-                            cmd.no_spawn()?;
-                        }
-                        Executor::exec(id)?;
-                        for bind in &binds {
-                            Executor::exec(*bind)?
-                        }
-                        Ok(())
-                    },
-                    service.unit_id(),
-                )
-            } else {
-                let _ = Self::exec_reload(service);
-                let _ = Executor::exec(id);
-            }
+            Self::restart(service);
             return;
         }
 
@@ -209,7 +186,41 @@ impl ServiceExecutor {
         }
 
         //停止服务后设置Unit状态
-        service.mut_unit_base().set_state(UnitState::Disabled);
+        service.unit_base_mut().set_state(UnitState::Inactive);
+    }
+
+    /// ## 重启Service
+    pub fn restart(service: &mut ServiceUnit) -> Result<(), RuntimeError> {
+        let ns = service.service_part().restart_sec();
+        let binds = service.unit_base().unit_part().be_binded_by();
+        let binds = Vec::from(binds);
+        let id = service.unit_id();
+        if ns > 0 {
+            let cmds = service.service_part().exec_reload().clone();
+            TimerManager::push_timer(
+                Duration::from_nanos(ns),
+                move || {
+                    for cmd in &cmds {
+                        cmd.no_spawn()?;
+                    }
+                    Executor::exec(id)?;
+                    for bind in &binds {
+                        Executor::restart(*bind)?
+                    }
+                    Ok(())
+                },
+                service.unit_id(),
+            )
+        } else {
+            UnitManager::try_kill_running(id);
+            Self::exec_reload(service)?;
+            eprintln!("restart");
+            Self::exec(service)?;
+            for bind in &binds {
+                Executor::restart(*bind)?;
+            }
+        }
+        Ok(())
     }
 
     /// ## 显示退出Service
@@ -224,13 +235,13 @@ impl ServiceExecutor {
             TimerManager::push_timer(
                 Duration::from_nanos(ns),
                 move || {
-                    if UnitManager::is_running_unit(&id) {
-                        UnitManager::kill_running(id);
-                    }
+                    UnitManager::try_kill_running(id);
                     Ok(())
                 },
                 service.unit_id(),
             )
+        } else {
+            UnitManager::try_kill_running(id);
         }
     }
 }

+ 23 - 3
src/main.rs

@@ -3,9 +3,19 @@
 #![feature(slice_pattern)]
 #![feature(fn_traits)]
 
+use cfg_if::cfg_if;
+
 #[cfg(target_os = "dragonos")]
 extern crate drstd as std;
 
+cfg_if! {
+    if #[cfg(target_os = "dragonos")] {
+        extern crate drstd as std;
+        #[macro_use]
+        extern crate dsc;
+    }
+}
+
 extern crate hashbrown;
 
 mod contants;
@@ -13,6 +23,7 @@ mod error;
 mod executor;
 mod manager;
 mod parse;
+mod systemctl;
 mod task;
 mod time;
 mod unit;
@@ -29,13 +40,22 @@ pub struct FileDescriptor(usize);
 
 const DRAGON_REACH_UNIT_DIR: &'static str = "/etc/reach/system/";
 
+extern "C" fn thread_function(_: *mut std::ffi::c_void) -> *mut std::ffi::c_void {
+    println!("Child thread");
+    // loop{}
+    core::ptr::null_mut() as *mut std::ffi::c_void
+}
+
 #[cfg(target_os = "dragonos")]
 #[no_mangle]
 fn main() {
     use manager::timer_manager::TimerManager;
     use parse::UnitParser;
 
-    use crate::{executor::Executor, manager::Manager};
+    use crate::{executor::Executor, manager::Manager, systemctl::listener::Systemctl};
+
+    // 初始化
+    Systemctl::init();
 
     let mut units_file_name = Vec::new();
     //读取目录里面的unit文件
@@ -66,8 +86,6 @@ fn main() {
         if id != 0 {
             if let Err(e) = Executor::exec(id) {
                 eprintln!("Err:{}", e.error_format());
-            } else {
-                println!("Service {} startup success...", id);
             }
         }
     }
@@ -80,6 +98,8 @@ fn main() {
         Manager::check_cmd_proc();
         // 检查计时器任务
         TimerManager::check_timer();
+        // 监听systemctl
+        Systemctl::ctl_listen();
     }
 }
 

+ 243 - 0
src/manager/ctl_manager/mod.rs

@@ -0,0 +1,243 @@
+use lazy_static::lazy_static;
+use std::fs::File;
+use std::io::Write;
+use std::os::fd::FromRawFd;
+use std::string::String;
+use std::string::ToString;
+use std::sync::Arc;
+use std::{eprint, eprintln, format};
+use std::{libc, print, println};
+use std::{sync::Mutex, vec::Vec};
+
+use crate::error::runtime_error::RuntimeError;
+use crate::error::runtime_error::RuntimeErrorType;
+use crate::error::ErrorFormat;
+use crate::parse::parse_util::UnitParseUtil;
+use crate::systemctl::ctl_parser::Pattern;
+use crate::systemctl::ctl_path;
+use crate::systemctl::listener::Command;
+use crate::unit::Unit;
+use crate::unit::UnitState;
+
+use super::{UnitManager, ID_TO_UNIT_MAP};
+pub struct CtlManager;
+
+lazy_static! {
+    static ref CTL_WRITER: Mutex<Arc<File>> = {
+        let file = CtlManager::init_ctl_writer();
+        Mutex::new(Arc::new(file))
+    };
+}
+
+impl CtlManager {
+    pub fn exec_ctl(cmd: Command) -> Result<(), RuntimeError> {
+        // TODO:目前假设一个时刻只有一个进程使用systemdctl,后续应该使用DBus等更灵活的进程通信方式
+        match cmd.operation {
+            crate::systemctl::ctl_parser::CommandOperation::ListUnits => {
+                Self::list_unit(cmd.patterns)
+            }
+            crate::systemctl::ctl_parser::CommandOperation::Start => Self::start(cmd.args.unwrap()),
+            crate::systemctl::ctl_parser::CommandOperation::Restart => {
+                Self::restart(cmd.args.unwrap(), false)
+            }
+            crate::systemctl::ctl_parser::CommandOperation::Stop => Self::stop(cmd.args.unwrap()),
+            crate::systemctl::ctl_parser::CommandOperation::Reboot => Ok(Self::reboot()),
+            crate::systemctl::ctl_parser::CommandOperation::ListSockets => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ListTimers => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Reload => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::TryRestart => {
+                Self::restart(cmd.args.unwrap(), true)
+            }
+            crate::systemctl::ctl_parser::CommandOperation::ReloadOrRestart => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ReloadOrTryRestart => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Isolate => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Kill => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::IsActive => {
+                let mut patterns = cmd.patterns.clone();
+                patterns.push(Pattern::State(UnitState::Active));
+                Self::list_unit(patterns)
+            }
+            crate::systemctl::ctl_parser::CommandOperation::IsFailed => {
+                let mut patterns = cmd.patterns.clone();
+                patterns.push(Pattern::State(UnitState::Failed));
+                Self::list_unit(patterns)
+            }
+            crate::systemctl::ctl_parser::CommandOperation::Status => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Show => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Cat => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::SetProperty => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Help => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ResetFailed => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ListDependencies => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ListUnitFiles => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Enable => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Disable => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Reenable => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Preset => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::PresetAll => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::IsEnabled => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Mask => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::UnMask => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Link => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::AddWants => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::AddRequires => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Edit => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::GetDefault => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::SetDefault => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ListMachines => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ListJobs => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Cancel => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Snapshot => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Delete => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ShowEnvironment => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::SetEnvironment => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::UnsetEnvironment => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::ImportEnvironment => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::DeamonReload => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::DeamonReexec => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::IsSystemRunning => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Default => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Rescue => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Emergency => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Halt => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Poweroff => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Kexec => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Exit => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::SwitchRoot => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Suspend => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::Hibernate => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::HybridSleep => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::UnSupported => todo!(),
+            crate::systemctl::ctl_parser::CommandOperation::None => {
+                println!("No such command!");
+                return Err(RuntimeError::new(RuntimeErrorType::InvalidInput));
+            }
+        }
+    }
+
+    pub fn list_unit(pattern: Vec<Pattern>) -> Result<(), RuntimeError> {
+        let units = Self::filter_units(pattern)?;
+
+        let mut res = "UNIT\t\t\t\tLOAD\t\tACTIVE\t\tSUB\t\tDESCRIPTION".to_string();
+        res.push_str("\n----------------------------------------------------------------------------------------------");
+        for unit in units {
+            res = format!("{}\n{}", res, unit.lock().unwrap().unit_base().unit_info());
+        }
+
+        // if let Err(err) = CTL_WRITER.lock().unwrap().write_all(res.as_bytes()) {
+        //     eprintln!("write ctl error :{}", err);
+        // }
+        println!("{}", res);
+        Ok(())
+    }
+
+    pub fn stop(names: Vec<String>) -> Result<(), RuntimeError> {
+        // TODO:打日志
+        for name in names {
+            match UnitManager::get_unit_with_name(&name) {
+                Some(unit) => {
+                    unit.lock().unwrap().exit();
+                }
+                None => {
+                    eprintln!("{} is not a unit", name);
+                    return Err(RuntimeError::new(RuntimeErrorType::FileNotFound));
+                }
+            }
+        }
+        Ok(())
+    }
+
+    pub fn start(names: Vec<String>) -> Result<(), RuntimeError> {
+        // TODO:打日志
+        for name in names {
+            match UnitManager::get_unit_with_name(&name) {
+                Some(unit) => unit.lock().unwrap().run()?,
+                None => match UnitParseUtil::parse_unit_no_type(&name) {
+                    Ok(i) => {
+                        let unit = UnitManager::get_unit_with_id(&i).unwrap();
+                        let mut unit = unit.lock().unwrap();
+                        unit.run()?;
+                    }
+                    Err(err) => {
+                        eprintln!("parse unit {} error :{}", name, err.error_format());
+                    }
+                },
+            }
+        }
+        Ok(())
+    }
+
+    pub fn reboot() {
+        #[cfg(target_os = "dragonos")]
+        unsafe {
+            dsc::syscall!(SYS_REBOOT)
+        };
+    }
+
+    pub fn restart(names: Vec<String>, is_try: bool) -> Result<(), RuntimeError> {
+        // TODO:打日志
+        for name in names {
+            match UnitManager::get_unit_with_name(&name) {
+                Some(unit) => {
+                    let mut unit = unit.lock().unwrap();
+                    if is_try && *unit.unit_base().state() == UnitState::Active {
+                        unit.restart()?;
+                    } else {
+                        unit.restart()?;
+                    }
+                }
+                None => match UnitParseUtil::parse_unit_no_type(&name) {
+                    Ok(i) => {
+                        let unit = UnitManager::get_unit_with_id(&i).unwrap();
+                        unit.lock().unwrap().run()?;
+                    }
+                    Err(err) => {
+                        eprintln!("parse unit {} error :{}", name, err.error_format());
+                        return Err(RuntimeError::new(RuntimeErrorType::InvalidFileFormat));
+                    }
+                },
+            }
+        }
+        Ok(())
+    }
+
+    pub fn init_ctl_writer() -> File {
+        let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_WRONLY) };
+        if fd < 0 {
+            panic!("open ctl pipe error");
+        }
+        unsafe { File::from_raw_fd(fd) }
+    }
+
+    pub fn filter_units(patterns: Vec<Pattern>) -> Result<Vec<Arc<Mutex<dyn Unit>>>, RuntimeError> {
+        let reader = ID_TO_UNIT_MAP.read().unwrap();
+
+        // TODO: 这里可以优化
+        let bindings = reader.values().collect::<Vec<_>>();
+        let mut units = Vec::new();
+        for unit in bindings {
+            units.push(unit.clone());
+        }
+        for pat in patterns {
+            match pat {
+                Pattern::Type(t) => {
+                    units = units
+                        .into_iter()
+                        .filter(|x| x.lock().unwrap().unit_type() == t)
+                        .collect::<Vec<_>>()
+                }
+                Pattern::State(s) => {
+                    units = units
+                        .into_iter()
+                        .filter(|x| *x.lock().unwrap().unit_base().state() == s)
+                        .collect::<Vec<_>>()
+                }
+                Pattern::None => {}
+                _ => {
+                    return Err(RuntimeError::new(RuntimeErrorType::InvalidInput));
+                }
+            }
+        }
+        Ok(units)
+    }
+}

+ 1 - 0
src/manager/mod.rs

@@ -2,6 +2,7 @@ use std::{eprint, eprintln, print, println, vec::Vec};
 
 pub mod timer_manager;
 pub mod unit_manager;
+pub mod ctl_manager;
 
 pub use unit_manager::*;
 

+ 29 - 23
src/manager/unit_manager/mod.rs

@@ -20,10 +20,10 @@ lazy_static! {
     static ref IDLE_SERVIEC_DEQUE: Mutex<VecDeque<usize>> = Mutex::new(VecDeque::new());
 
     // id到unit的映射表,全局的Unit管理表
-    static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new());
+    pub(super) static ref ID_TO_UNIT_MAP: RwLock<HashMap<usize,Arc<Mutex<dyn Unit>>>> = RwLock::new(HashMap::new());
 
     // 辅助表,通过服务名映射其id
-    static ref PATH_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new());
+    static ref NAME_TO_UNIT_MAP: RwLock<HashMap<u64,usize>> = RwLock::new(HashMap::new());
 
     // 全局运行中的Unit表
     pub(super) static ref RUNNING_TABLE: RwLock<RunningTableManager> = RwLock::new(RunningTableManager { running_table: HashMap::new() });
@@ -54,27 +54,27 @@ unsafe impl Sync for UnitManager {}
 #[allow(dead_code)]
 impl UnitManager {
     /// 插入一条path到unit_id的映射
-    pub fn insert_into_path_table(path: &str, unit: usize) {
+    pub fn insert_into_name_table(path: &str, unit: usize) {
         let mut hasher = DefaultHasher::new();
         path.hash(&mut hasher);
         let hash = hasher.finish();
-        PATH_TO_UNIT_MAP.write().unwrap().insert(hash, unit);
+        NAME_TO_UNIT_MAP.write().unwrap().insert(hash, unit);
     }
 
     // 判断当前是否已经有了对应path的Unit
-    pub fn contains_path(path: &str) -> bool {
+    pub fn contains_name(path: &str) -> bool {
         let mut hasher = DefaultHasher::new();
         path.hash(&mut hasher);
         let hash = hasher.finish();
-        PATH_TO_UNIT_MAP.read().unwrap().contains_key(&hash)
+        NAME_TO_UNIT_MAP.read().unwrap().contains_key(&hash)
     }
 
     // 通过path获取到Unit
-    pub fn get_unit_with_path(path: &str) -> Option<Arc<Mutex<dyn Unit>>> {
+    pub fn get_unit_with_name(name: &str) -> Option<Arc<Mutex<dyn Unit>>> {
         let mut hasher = DefaultHasher::new();
-        path.hash(&mut hasher);
+        name.hash(&mut hasher);
         let hash = hasher.finish();
-        let map = PATH_TO_UNIT_MAP.read().unwrap();
+        let map = NAME_TO_UNIT_MAP.read().unwrap();
         let id = match map.get(&hash) {
             Some(id) => id,
             None => {
@@ -99,7 +99,7 @@ impl UnitManager {
         let mut hasher = DefaultHasher::new();
         path.hash(&mut hasher);
         let hash = hasher.finish();
-        PATH_TO_UNIT_MAP.read().unwrap().get(&hash).cloned()
+        NAME_TO_UNIT_MAP.read().unwrap().get(&hash).cloned()
     }
 
     // 判断该Unit是否正在运行中
@@ -202,11 +202,11 @@ impl UnitManager {
         // 处理before段,将before段的Unit添加此Unit为After
         for (id, unit) in manager.iter() {
             let mut unit = unit.lock().unwrap();
-            let before = unit.mut_unit_base().unit_part().before();
+            let before = unit.unit_base_mut().unit_part().before();
             for rid in before {
                 let req = UnitManager::get_unit_with_id(rid).unwrap();
                 let mut req = req.lock().unwrap();
-                req.mut_unit_base().mut_unit_part().push_after_unit(*id);
+                req.unit_base_mut().mut_unit_part().push_after_unit(*id);
             }
         }
 
@@ -214,31 +214,37 @@ impl UnitManager {
             let mut unit = unit.lock().unwrap();
 
             // 处理binds_to段
-            let binds_to = unit.mut_unit_base().unit_part().binds_to();
+            let binds_to = unit.unit_base_mut().unit_part().binds_to();
             for rid in binds_to {
                 let req = UnitManager::get_unit_with_id(rid).unwrap();
                 let mut req = req.lock().unwrap();
-                req.mut_unit_base().mut_unit_part().push_be_binded_by(*id);
+                req.unit_base_mut().mut_unit_part().push_be_binded_by(*id);
             }
 
             // 处理part_of段
-            let part_of = unit.mut_unit_base().unit_part().part_of();
+            let part_of = unit.unit_base_mut().unit_part().part_of();
             for rid in part_of {
                 let req = UnitManager::get_unit_with_id(rid).unwrap();
                 let mut req = req.lock().unwrap();
-                req.mut_unit_base().mut_unit_part().push_be_binded_by(*id);
+                req.unit_base_mut().mut_unit_part().push_be_binded_by(*id);
             }
         }
     }
 
-    /// ## 杀死Unit进程
-    pub fn kill_running(id: usize) {
+    /// ## 如果Unit进程正在运行则杀死Unit进程
+    pub fn try_kill_running(id: usize) -> bool {
         if Self::is_running_unit(&id) {
-            let mut running_manager = RUNNING_TABLE.write().unwrap();
-            let unit = running_manager.running_table.get_mut(&id).unwrap();
-            let _ = unit.kill();
-            println!("kill:{}", id);
-            running_manager.running_table.remove(&id);
+            Self::kill_running(id);
+            return true;
         }
+        return false;
+    }
+
+    pub fn kill_running(id: usize) {
+        let mut running_manager = RUNNING_TABLE.write().unwrap();
+        let unit = running_manager.running_table.get_mut(&id).unwrap();
+        let _ = unit.kill();
+        println!("kill:{}", id);
+        running_manager.running_table.remove(&id);
     }
 }

+ 30 - 3
src/parse/mod.rs

@@ -1,5 +1,6 @@
 use crate::error::parse_error::ParseErrorType;
 use crate::manager::UnitManager;
+use crate::unit::timer::{TimerPart, TimerUnitAttr};
 use crate::unit::{BaseUnit, Unit};
 use crate::DRAGON_REACH_UNIT_DIR;
 use crate::{
@@ -147,6 +148,26 @@ lazy_static! {
         table.insert("ns", 1);
         table
     };
+
+    pub static ref TIMER_UNIT_ATTR_TABLE: HashMap<&'static str, TimerUnitAttr> = {
+        let mut map = HashMap::new();
+        map.insert("OnActiveSec", TimerUnitAttr::OnActiveSec);
+        map.insert("OnBootSec", TimerUnitAttr::OnBootSec);
+        map.insert("OnStartupSec", TimerUnitAttr::OnStartUpSec);
+        map.insert("OnUnitActiveSec", TimerUnitAttr::OnUnitInactiveSec);
+        map.insert("OnUnitInactiveSec", TimerUnitAttr::OnUnitInactiveSec);
+        map.insert("OnCalendar", TimerUnitAttr::OnCalendar);
+        map.insert("AccuracySec", TimerUnitAttr::AccuarcySec);
+        map.insert("RandomizedDelaySec", TimerUnitAttr::RandomizedDelaySec);
+        map.insert("FixedRandomDelay", TimerUnitAttr::FixedRandomDelay);
+        map.insert("OnClockChange", TimerUnitAttr::OnClockChange);
+        map.insert("OnTimezoneChange", TimerUnitAttr::OnTimeZoneChange);
+        map.insert("Unit", TimerUnitAttr::Unit);
+        map.insert("Persistent", TimerUnitAttr::Persistent);
+        map.insert("WakeSystem", TimerUnitAttr::WakeSystem);
+        map.insert("RemainAfterElapse", TimerUnitAttr::RemainAfterElapse);
+        map
+    };
 }
 
 //用于解析Unit共有段的方法
@@ -216,9 +237,13 @@ impl UnitParser {
         path: &str,
         unit_type: UnitType,
     ) -> Result<usize, ParseError> {
+        let name = match path.rfind("/") {
+            Some(size) => String::from(&path[size..]),
+            None => String::from(path),
+        };
         // 如果该文件已解析过,则直接返回id
-        if UnitManager::contains_path(path) {
-            let unit = UnitManager::get_unit_with_path(path).unwrap();
+        if UnitManager::contains_name(&name) {
+            let unit = UnitManager::get_unit_with_name(&name).unwrap();
             let unit = unit.lock().unwrap();
             return Ok(unit.unit_id());
         }
@@ -338,12 +363,14 @@ impl UnitParser {
             }
             i += 1;
         }
+
         unit.set_unit_base(unit_base);
+        unit.set_unit_name(name.clone());
         let id = unit.set_unit_id();
         unit.init();
         let dret: Arc<Mutex<dyn Unit>> = Arc::new(Mutex::new(unit));
         UnitManager::insert_unit_with_id(id, dret);
-        UnitManager::insert_into_path_table(path, id);
+        UnitManager::insert_into_name_table(&name, id);
 
         return Ok(id);
     }

+ 104 - 96
src/parse/parse_util/mod.rs

@@ -578,97 +578,103 @@ impl UnitParseUtil {
     ///
     /// @return 解析成功则返回Ok(u64),否则返回Err
     pub fn parse_sec(s: &str) -> Result<u64, ParseError> {
-        //下列参数分别记录整数部分,小数部分以及单位
-        let integer: u64;
-        let mut frac: u64 = 0;
-        let unit: &str;
-
-        match s.find('.') {
-            Some(idx) => {
-                //解析整数部分
-                integer = match s[..idx].parse::<u64>() {
-                    Ok(val) => val,
-                    Err(_) => {
-                        return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0))
-                    }
-                };
-                //获得小数+单位的字符串
-                let frac_and_unit = &s[(idx + 1)..];
-                match frac_and_unit.find(|c: char| !c.is_digit(10)) {
-                    Some(val) => {
-                        //匹配小数部分
-                        frac = match frac_and_unit[..val].parse::<u64>() {
-                            Ok(val) => val,
-                            Err(_) => {
-                                return Err(ParseError::new(
-                                    ParseErrorType::EINVAL,
-                                    String::new(),
-                                    0,
-                                ))
-                            }
-                        };
-                        //单位部分
-                        unit = &frac_and_unit[val..];
-                    }
-                    None => {
-                        //没有单位的情况,直接匹配小数
-                        frac = match frac_and_unit.parse::<u64>() {
-                            Ok(val) => val,
-                            Err(_) => {
-                                return Err(ParseError::new(
-                                    ParseErrorType::EINVAL,
-                                    String::new(),
-                                    0,
-                                ))
-                            }
-                        };
-                        unit = "";
-                    }
-                };
-            }
-            None => {
-                //没有小数点则直接匹配整数部分和单位部分
-                match s.find(|c: char| !c.is_digit(10)) {
-                    Some(idx) => {
-                        integer = match s[..idx].parse::<u64>() {
-                            Ok(val) => val,
-                            Err(_) => {
-                                return Err(ParseError::new(
-                                    ParseErrorType::EINVAL,
-                                    String::new(),
-                                    0,
-                                ))
-                            }
-                        };
-                        unit = &s[idx..];
-                    }
-                    None => {
-                        integer = match s.parse::<u64>() {
-                            Ok(val) => val,
-                            Err(_) => {
-                                return Err(ParseError::new(
-                                    ParseErrorType::EINVAL,
-                                    String::new(),
-                                    0,
-                                ))
-                            }
-                        };
-                        unit = "";
-                    }
-                };
-            }
-        };
+        let ss = s.split_whitespace().collect::<Vec<&str>>();
+        let mut ret = 0;
+        for s in ss {
+            //下列参数分别记录整数部分,小数部分以及单位
+            let integer: u64;
+            let mut frac: u64 = 0;
+            let unit: &str;
+
+            match s.find('.') {
+                Some(idx) => {
+                    //解析整数部分
+                    integer = match s[..idx].parse::<u64>() {
+                        Ok(val) => val,
+                        Err(_) => {
+                            return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0))
+                        }
+                    };
+                    //获得小数+单位的字符串
+                    let frac_and_unit = &s[(idx + 1)..];
+                    match frac_and_unit.find(|c: char| !c.is_digit(10)) {
+                        Some(val) => {
+                            //匹配小数部分
+                            frac = match frac_and_unit[..val].parse::<u64>() {
+                                Ok(val) => val,
+                                Err(_) => {
+                                    return Err(ParseError::new(
+                                        ParseErrorType::EINVAL,
+                                        String::new(),
+                                        0,
+                                    ))
+                                }
+                            };
+                            //单位部分
+                            unit = &frac_and_unit[val..];
+                        }
+                        None => {
+                            //没有单位的情况,直接匹配小数
+                            frac = match frac_and_unit.parse::<u64>() {
+                                Ok(val) => val,
+                                Err(_) => {
+                                    return Err(ParseError::new(
+                                        ParseErrorType::EINVAL,
+                                        String::new(),
+                                        0,
+                                    ))
+                                }
+                            };
+                            unit = "";
+                        }
+                    };
+                }
+                None => {
+                    //没有小数点则直接匹配整数部分和单位部分
+                    match s.find(|c: char| !c.is_digit(10)) {
+                        Some(idx) => {
+                            integer = match s[..idx].parse::<u64>() {
+                                Ok(val) => val,
+                                Err(_) => {
+                                    return Err(ParseError::new(
+                                        ParseErrorType::EINVAL,
+                                        String::new(),
+                                        0,
+                                    ))
+                                }
+                            };
+                            unit = &s[idx..];
+                        }
+                        None => {
+                            integer = match s.parse::<u64>() {
+                                Ok(val) => val,
+                                Err(_) => {
+                                    return Err(ParseError::new(
+                                        ParseErrorType::EINVAL,
+                                        String::new(),
+                                        0,
+                                    ))
+                                }
+                            };
+                            unit = "";
+                        }
+                    };
+                }
+            };
 
-        //从时间单位转换表中获取到单位转换为ns的倍数
-        let factor = match SEC_UNIT_TABLE.get(unit) {
-            Some(val) => val,
-            None => {
-                return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
-            }
-        };
+            //从时间单位转换表中获取到单位转换为ns的倍数
+            let factor = match SEC_UNIT_TABLE.get(unit) {
+                Some(val) => val,
+                None => {
+                    return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0));
+                }
+            };
+
+            ret += integer * factor + (frac * factor) / (10u64.pow(frac.to_string().len() as u32));
+        }
 
         //计算ns
-        return Ok(integer * factor + (frac * factor) / (10u64.pow(frac.to_string().len() as u32)));
+        return Ok(ret);
     }
     /// @brief 判断对应路径是否为目录
     ///
@@ -687,16 +693,18 @@ impl UnitParseUtil {
 
     ///// ## 通过文件名解析该Unit的类型
     pub fn parse_type(path: &str) -> UnitType {
+        let mut ret: &str;
         if let Some(index) = path.rfind('.') {
-            let result = &path[index + 1..];
-            match result {
-                "service" => return UnitType::Service,
-                "target" => return UnitType::Target,
-                //TODO: 添加文件类型
-                _ => return UnitType::Unknown,
-            }
+            ret = &path[index + 1..];
+        } else {
+            ret = path;
+        }
+        match ret {
+            "service" => return UnitType::Service,
+            "target" => return UnitType::Target,
+            //TODO: 添加文件类型
+            _ => return UnitType::Unknown,
         }
-        UnitType::Unknown
     }
 
     /// ## 将读取环境变量文件解析为环境变量集合

+ 369 - 0
src/systemctl/ctl_parser/mod.rs

@@ -0,0 +1,369 @@
+use crate::error::parse_error::{ParseError, ParseErrorType};
+use crate::parse::parse_util::UnitParseUtil;
+use crate::unit::{UnitState, UnitType};
+use hashbrown::HashMap;
+use lazy_static::lazy_static;
+use std::format;
+use std::string::String;
+use std::string::ToString;
+use std::vec::Vec;
+
+use super::listener::Command;
+
+#[derive(Debug, Clone)]
+pub enum CommandOperation {
+    ListUnits,
+    ListSockets,
+    ListTimers,
+    Start,
+    Restart,
+    Stop,
+    Reload,
+    TryRestart,
+    ReloadOrRestart,
+    ReloadOrTryRestart,
+    Isolate,
+    Kill,
+    IsActive,
+    IsFailed,
+    Status,
+    Show,
+    Cat,
+    SetProperty,
+    Help,
+    ResetFailed,
+    ListDependencies,
+    ListUnitFiles,
+    Enable,
+    Disable,
+    Reenable,
+    Preset,
+    PresetAll,
+    IsEnabled,
+    Mask,
+    UnMask,
+    Link,
+    AddWants,
+    AddRequires,
+    Edit,
+    GetDefault,
+    SetDefault,
+    ListMachines,
+    ListJobs,
+    Cancel,
+    Snapshot,
+    Delete,
+    ShowEnvironment,
+    SetEnvironment,
+    UnsetEnvironment,
+    ImportEnvironment,
+    DeamonReload,
+    DeamonReexec,
+    IsSystemRunning,
+    Default,
+    Rescue,
+    Emergency,
+    Halt,
+    Poweroff,
+    Reboot,
+    Kexec,
+    Exit,
+    SwitchRoot,
+    Suspend,
+    Hibernate,
+    HybridSleep,
+    UnSupported,
+    None,
+}
+
+#[derive(Debug, Clone)]
+pub enum Pattern {
+    Help,
+    Version,
+    System,
+    Host(String),
+    Machine(String),
+    Type(UnitType),
+    State(UnitState),
+    Property(String),
+    All,
+    Full,
+    Recursive,
+    Reverse,
+    JobMode(String),
+    ShowTypes,
+    IgnoreInhibitors,
+    KillWho(String),
+    Signal(String),
+    Now,
+    Quiet,
+    NoBlock,
+    NoWall,
+    NoReload,
+    NoLegend,
+    NoPaper,
+    NoAskPassword,
+    Global,
+    Runtime,
+    Force,
+    PresetMode,
+    Root(String),
+    Lines(i32),
+    Output(String),
+    Plain,
+    None,
+}
+
+impl ToString for Pattern {
+    fn to_string(&self) -> String {
+        match self {
+            Pattern::Help => "help".to_string(),
+            Pattern::Version => "version".to_string(),
+            Pattern::System => "system".to_string(),
+            Pattern::Host(s) => format!("{}={}", "host".to_string(), s),
+            Pattern::Machine(s) => format!("{}={}", "machine".to_string(), s),
+            Pattern::Type(t) => format!("{}={:?}", "type".to_string(), t),
+            Pattern::State(s) => format!("{}={:?}", "state".to_string(), s),
+            Pattern::Property(s) => format!("{}={}", "property".to_string(), s),
+            Pattern::All => "all".to_string(),
+            Pattern::Full => "full".to_string(),
+            Pattern::Recursive => "recursive".to_string(),
+            Pattern::Reverse => "reverse".to_string(),
+            Pattern::JobMode(s) => format!("{}={}", "job-mode".to_string(), s),
+            Pattern::ShowTypes => "show-types".to_string(),
+            Pattern::IgnoreInhibitors => "ignore-inhibitors".to_string(),
+            Pattern::KillWho(s) => format!("{}={}", "kill-who".to_string(), s),
+            Pattern::Signal(s) => format!("{}={}", "signal".to_string(), s),
+            Pattern::Now => "now".to_string(),
+            Pattern::Quiet => "quiet".to_string(),
+            Pattern::NoBlock => "no-block".to_string(),
+            Pattern::NoWall => "no-wall".to_string(),
+            Pattern::NoReload => "no-reload".to_string(),
+            Pattern::NoLegend => "no-legend".to_string(),
+            Pattern::NoPaper => "no-paper".to_string(),
+            Pattern::NoAskPassword => "no-ask-password".to_string(),
+            Pattern::Global => "global".to_string(),
+            Pattern::Runtime => "runtime".to_string(),
+            Pattern::Force => "force".to_string(),
+            Pattern::PresetMode => "preset-mode".to_string(),
+            Pattern::Root(s) => format!("{}={}", "root".to_string(), s),
+            Pattern::Lines(i) => format!("{}={}", "lines".to_string(), i),
+            Pattern::Output(s) => format!("{}={}", "output".to_string(), s),
+            Pattern::Plain => "plain".to_string(),
+            Pattern::None => "none".to_string(),
+        }
+    }
+}
+
+lazy_static! {
+    pub static ref CTL_COMMAND: HashMap<&'static str, CommandOperation> = {
+        let mut map = HashMap::new();
+        map.insert("list-units", CommandOperation::ListUnits);
+        map.insert("list-sockets", CommandOperation::UnSupported);
+        map.insert("list-timers", CommandOperation::UnSupported);
+        map.insert("start", CommandOperation::Start);
+        map.insert("stop", CommandOperation::Stop);
+        map.insert("reload", CommandOperation::UnSupported);
+        map.insert("restart", CommandOperation::Restart);
+        map.insert("try-restart", CommandOperation::TryRestart);
+        map.insert("reload-or-restart", CommandOperation::ReloadOrRestart);
+        map.insert(
+            "reload-or-try-restart",
+            CommandOperation::ReloadOrTryRestart,
+        );
+        map.insert("isolate", CommandOperation::Isolate);
+        map.insert("kill", CommandOperation::Kill);
+        map.insert("is-active", CommandOperation::IsActive);
+        map.insert("is-failed", CommandOperation::IsFailed);
+        map.insert("status", CommandOperation::Status);
+        map.insert("show", CommandOperation::Show);
+        map.insert("cat", CommandOperation::Cat);
+        map.insert("set-property", CommandOperation::SetProperty);
+        map.insert("help", CommandOperation::Help);
+        map.insert("reset-failed", CommandOperation::ResetFailed);
+        map.insert("list-dependencies", CommandOperation::ListDependencies);
+        map.insert("list-unit-files", CommandOperation::ListUnitFiles);
+        map.insert("enable", CommandOperation::Enable);
+        map.insert("disable", CommandOperation::Disable);
+        map.insert("reenable", CommandOperation::Reenable);
+        map.insert("preset", CommandOperation::Preset);
+        map.insert("preset-all", CommandOperation::PresetAll);
+        map.insert("is-enabled", CommandOperation::IsEnabled);
+        map.insert("mask", CommandOperation::Mask);
+        map.insert("unmask", CommandOperation::UnMask);
+        map.insert("link", CommandOperation::Link);
+        map.insert("add-wants", CommandOperation::AddWants);
+        map.insert("add-requires", CommandOperation::AddRequires);
+        map.insert("edit", CommandOperation::Edit);
+        map.insert("get-default", CommandOperation::GetDefault);
+        map.insert("set-default", CommandOperation::SetDefault);
+        map.insert("list-machines", CommandOperation::ListMachines);
+        map.insert("list-jobs", CommandOperation::ListJobs);
+        map.insert("cancel", CommandOperation::Cancel);
+        map.insert("snapshot", CommandOperation::Snapshot);
+        map.insert("delete", CommandOperation::Delete);
+        map.insert("show-environment", CommandOperation::ShowEnvironment);
+        map.insert("set-environment", CommandOperation::SetEnvironment);
+        map.insert("unset-environment", CommandOperation::UnsetEnvironment);
+        map.insert("import-environment", CommandOperation::ImportEnvironment);
+        map.insert("daemon-reload", CommandOperation::DeamonReload);
+        map.insert("daemon-reexec", CommandOperation::DeamonReexec);
+        map.insert("is-system-running", CommandOperation::IsSystemRunning);
+        map.insert("default", CommandOperation::Default);
+        map.insert("rescue", CommandOperation::Rescue);
+        map.insert("emergency", CommandOperation::Emergency);
+        map.insert("halt", CommandOperation::Halt);
+        map.insert("poweroff", CommandOperation::Poweroff);
+        map.insert("reboot", CommandOperation::Reboot);
+        map.insert("kexec", CommandOperation::Kexec);
+        map.insert("exit", CommandOperation::Exit);
+        map.insert("switch-root", CommandOperation::SwitchRoot);
+        map.insert("suspend", CommandOperation::Suspend);
+        map.insert("hibernate", CommandOperation::Hibernate);
+        map.insert("hybrid-sleep", CommandOperation::HybridSleep);
+        map
+    };
+    pub static ref CTL_PATTERN: HashMap<&'static str, Pattern> = {
+        let mut map = HashMap::new();
+        map.insert("help", Pattern::Help);
+        map.insert("version", Pattern::Version);
+        map.insert("system", Pattern::System);
+        map.insert("host", Pattern::Host(String::new()));
+        map.insert("machine", Pattern::Machine(String::new()));
+        map.insert("type", Pattern::Type(UnitType::Unknown));
+        map.insert("state", Pattern::State(UnitState::Active));
+        map.insert("property", Pattern::Property(String::new()));
+        map.insert("all", Pattern::All);
+        map.insert("full", Pattern::Full);
+        map.insert("recursive", Pattern::Recursive);
+        map.insert("reverse", Pattern::Reverse);
+        map.insert("job-mode", Pattern::JobMode(String::new()));
+        map.insert("show-types", Pattern::ShowTypes);
+        map.insert("ignore-inhibitors", Pattern::IgnoreInhibitors);
+        map.insert("kill-who", Pattern::KillWho(String::new()));
+        map.insert("signal", Pattern::Signal(String::new()));
+        map.insert("now", Pattern::Now);
+        map.insert("quiet", Pattern::Quiet);
+        map.insert("no-block", Pattern::NoBlock);
+        map.insert("no-wall", Pattern::NoWall);
+        map.insert("no-reload", Pattern::NoReload);
+        map.insert("no-legend", Pattern::NoLegend);
+        map.insert("no-paper", Pattern::NoPaper);
+        map.insert("no-ask-password", Pattern::NoAskPassword);
+        map.insert("global", Pattern::Global);
+        map.insert("runtime", Pattern::Runtime);
+        map.insert("force", Pattern::Force);
+        map.insert("preset-mode", Pattern::PresetMode);
+        map.insert("root", Pattern::Root(String::new()));
+        map.insert("lines", Pattern::Lines(-1));
+        map.insert("output", Pattern::Output(String::new()));
+        map.insert("plain", Pattern::Plain);
+        map
+    };
+}
+
+pub struct CtlParser;
+
+impl CtlParser {
+    pub fn parse_ctl(s: &str) -> Result<Command, ParseError> {
+        let mut words = s.split_whitespace().collect::<Vec<&str>>();
+        let mut ctl = Command::default();
+        if let Some(op) = CTL_COMMAND.get(words.remove(0)) {
+            ctl.operation = op.clone();
+        }
+
+        let mut opt: Option<Vec<String>>;
+        match ctl.operation {
+            CommandOperation::Start
+            | CommandOperation::Restart
+            | CommandOperation::Stop
+            | CommandOperation::TryRestart
+            | CommandOperation::Reload
+            | CommandOperation::AddRequires
+            | CommandOperation::AddWants
+            | CommandOperation::Kill
+            | CommandOperation::ListDependencies
+            | CommandOperation::Enable
+            | CommandOperation::Disable
+            | CommandOperation::Reenable
+            | CommandOperation::Preset
+            | CommandOperation::IsEnabled
+            | CommandOperation::Mask
+            | CommandOperation::UnMask
+            | CommandOperation::Link
+            | CommandOperation::Edit
+            | CommandOperation::SetDefault
+            | CommandOperation::SetEnvironment
+            | CommandOperation::UnsetEnvironment
+            | CommandOperation::ImportEnvironment => {
+                opt = Some(Vec::new());
+            }
+            _ => {
+                opt = None;
+            }
+        }
+
+        for word in words {
+            if word.starts_with("--") {
+                ctl.patterns.push(Self::parse_pattern(&word[2..])?);
+            } else {
+                if let Some(ref mut v) = opt {
+                    v.push(word.to_string());
+                } else {
+                    return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+                }
+            }
+        }
+
+        ctl.args = opt;
+
+        Ok(ctl)
+    }
+
+    fn parse_pattern(s: &str) -> Result<Pattern, ParseError> {
+        let pattern: Pattern;
+        if s.contains("=") {
+            let words = s.split("=").collect::<Vec<&str>>();
+            if words.len() > 2 {
+                return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+            }
+
+            let option = CTL_PATTERN.get(words[0]);
+            if let Some(p) = option {
+                pattern = match *p {
+                    Pattern::Host(_) => Pattern::Host(words[1].to_string()),
+                    Pattern::Machine(_) => Pattern::Machine(words[1].to_string()),
+                    Pattern::Type(_) => Pattern::Type(UnitParseUtil::parse_type(words[1])),
+                    Pattern::State(_) => {
+                        todo!()
+                    }
+                    Pattern::JobMode(_) => Pattern::JobMode(words[1].to_string()),
+                    Pattern::KillWho(_) => Pattern::KillWho(words[1].to_string()),
+                    Pattern::Lines(_) => match words[1].parse::<i32>() {
+                        Ok(val) => Pattern::Lines(val),
+                        Err(_) => {
+                            return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+                        }
+                    },
+                    Pattern::Output(_) => Pattern::Output(words[1].to_string()),
+                    Pattern::Property(_) => Pattern::Property(words[1].to_string()),
+                    Pattern::Root(_) => Pattern::Root(words[1].to_string()),
+                    Pattern::Signal(_) => Pattern::Signal(words[1].to_string()),
+                    _ => {
+                        return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+                    }
+                };
+            } else {
+                return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+            }
+        } else {
+            pattern = match CTL_PATTERN.get(s) {
+                Some(val) => val.clone(),
+                None => {
+                    return Err(ParseError::new(ParseErrorType::EINVAL, s.to_string(), 0));
+                }
+            };
+        }
+        return Ok(pattern);
+    }
+}

+ 102 - 0
src/systemctl/listener/mod.rs

@@ -0,0 +1,102 @@
+use lazy_static::lazy_static;
+use std::fs::{self, File};
+use std::io::{self, BufRead, BufReader, Read};
+use std::libc::c_str::CString;
+use std::os::fd::FromRawFd;
+use std::string::String;
+use std::sync::{Arc, Mutex};
+use std::vec::Vec;
+use std::{eprint, eprintln, libc};
+
+use crate::error::ErrorFormat;
+use crate::manager::ctl_manager::CtlManager;
+use crate::manager::UnitManager;
+
+use super::ctl_parser::{CommandOperation, CtlParser, Pattern};
+use super::{ctl_path, DRAGON_REACH_CTL_PIPE};
+
+lazy_static! {
+    static ref CTL_READER: Mutex<Arc<File>> = {
+        let file = Systemctl::init_listener();
+        Mutex::new(Arc::new(file))
+    };
+}
+
+pub struct Command {
+    pub(crate) operation: CommandOperation,
+    pub(crate) args: Option<Vec<String>>,
+    pub(crate) patterns: Vec<Pattern>,
+}
+
+impl Command {
+    fn new(op: CommandOperation, patterns: Vec<Pattern>, args: Option<Vec<String>>) -> Self {
+        Command {
+            operation: op,
+            args,
+            patterns: patterns,
+        }
+    }
+}
+
+impl Default for Command {
+    fn default() -> Self {
+        Command {
+            operation: CommandOperation::None,
+            args: None,
+            patterns: Vec::new(),
+        }
+    }
+}
+
+pub struct Systemctl;
+
+impl Systemctl {
+    pub fn init() {
+        Self::init_ctl_pipe();
+    }
+
+    pub fn init_listener() -> File {
+        let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_RDONLY | libc::O_NONBLOCK) };
+        if fd < 0 {
+            panic!("open ctl pipe error");
+        }
+        unsafe { File::from_raw_fd(fd) }
+    }
+
+    pub fn ctl_listen() {
+        let mut guard = CTL_READER.lock().unwrap();
+        let mut s = String::new();
+        if let Ok(size) = guard.read_to_string(&mut s) {
+            if size == 0 {
+                return;
+            }
+            match CtlParser::parse_ctl(&s) {
+                Ok(cmd) => {
+                    CtlManager::exec_ctl(cmd);
+                }
+                Err(err) => {
+                    eprintln!("parse tcl command error: {}", err.error_format());
+                }
+            }
+        }
+    }
+
+    fn is_ctl_exists() -> bool {
+        if let Ok(metadata) = fs::metadata(DRAGON_REACH_CTL_PIPE) {
+            metadata.is_file()
+        } else {
+            false
+        }
+    }
+
+    fn init_ctl_pipe() {
+        if !Self::is_ctl_exists() {
+            let path = ctl_path();
+            let ret = unsafe { libc::mkfifo(path.as_ptr(), 0o666) };
+            if ret != 0 {
+                // 创建管道失败打日志
+                panic!("create ctl pipe failed");
+            }
+        }
+    }
+}

+ 10 - 0
src/systemctl/mod.rs

@@ -0,0 +1,10 @@
+use std::libc::c_str::CString;
+
+pub mod ctl_parser;
+pub mod listener;
+
+pub const DRAGON_REACH_CTL_PIPE: &'static str = "/etc/reach/ipc/ctl";
+
+pub fn ctl_path() -> CString {
+    CString::new(DRAGON_REACH_CTL_PIPE).expect("Failed to create pipe CString")
+}

+ 125 - 7
src/unit/mod.rs

@@ -1,3 +1,7 @@
+use std::format;
+
+use std::string::ToString;
+
 use crate::error::parse_error::ParseError;
 use crate::error::parse_error::ParseErrorType;
 use crate::error::runtime_error::RuntimeError;
@@ -22,6 +26,7 @@ use std::vec::Vec;
 
 pub mod service;
 pub mod target;
+pub mod timer;
 
 use self::target::TargetUnit;
 
@@ -74,7 +79,7 @@ pub trait Unit: Sync + Send + Debug {
 
     fn unit_base(&self) -> &BaseUnit;
 
-    fn mut_unit_base(&mut self) -> &mut BaseUnit;
+    fn unit_base_mut(&mut self) -> &mut BaseUnit;
 
     fn unit_id(&self) -> usize;
 
@@ -88,32 +93,122 @@ pub trait Unit: Sync + Send + Debug {
     /// ### return OK(())/Err
     fn set_unit_id(&mut self) -> usize {
         let ret = generate_unit_id();
-        self.mut_unit_base().set_id(ret);
+        self.unit_base_mut().set_id(ret);
         ret
     }
 
     /// ## Unit退出后逻辑
     ///
     /// 一般只有可运行的Unit(如Service)需要重写此函数
-    fn after_exit(&mut self, _exit_status: ExitStatus) {}
+    fn after_exit(&mut self, _exit_status: ExitStatus) {
+        unimplemented!()
+    }
 
     /// ## 初始化Unit内任务的一些参数,各个Unit所需处理的不相同,故放在总的Unit trait
     fn init(&mut self) {}
 
     /// ## Unit的显式退出逻辑
     fn exit(&mut self);
+
+    fn set_unit_name(&mut self, name: String) {
+        self.unit_base_mut().unit_name = name;
+    }
+
+    /// ## Unit重启逻辑
+    fn restart(&mut self) -> Result<(), RuntimeError> {
+        unimplemented!()
+    }
 }
 
 //Unit状态
 #[allow(dead_code)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum UnitState {
-    Enabled,
-    Disabled,
-    Static,
+    Active,
+    Inactive,
+    Activating,
+    Deactivating,
+    Failed,
+    Reloading,
+    Maintenance,
+}
+
+impl ToString for UnitState {
+    fn to_string(&self) -> String {
+        match *self {
+            UnitState::Active => "active".to_string(),
+            UnitState::Inactive => "inactive".to_string(),
+            UnitState::Activating => "activeting".to_string(),
+            UnitState::Deactivating => "deactivating".to_string(),
+            UnitState::Failed => "failed".to_string(),
+            UnitState::Reloading => "reloading".to_string(),
+            UnitState::Maintenance => "maintenance".to_string(),
+        }
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum UnitSubState {
+    Running,
+    Waiting,
+    StartPre,
+    StartPost,
+    StopSigterm,
+    StopSigkill,
+    StopFinalSigterm,
+    StopFinalSigkill,
+    Dead,
+    AutoRestart,
+    Failed,
+    Activating,
+    Deactivating,
+    Plugged,
+    Unknown,
+}
+
+impl ToString for UnitSubState {
+    fn to_string(&self) -> String {
+        match *self {
+            UnitSubState::Running => "running".to_string(),
+            UnitSubState::Waiting => "waiting".to_string(),
+            UnitSubState::StartPre => "start-pre".to_string(),
+            UnitSubState::StartPost => "start-post".to_string(),
+            UnitSubState::StopSigterm => "stop-sigterm".to_string(),
+            UnitSubState::StopSigkill => "stop-sigkill".to_string(),
+            UnitSubState::StopFinalSigterm => "stop-final-sigterm".to_string(),
+            UnitSubState::StopFinalSigkill => "stop-final-sigkill".to_string(),
+            UnitSubState::Dead => "dead".to_string(),
+            UnitSubState::AutoRestart => "auto-restart".to_string(),
+            UnitSubState::Failed => "failed".to_string(),
+            UnitSubState::Activating => "activating".to_string(),
+            UnitSubState::Deactivating => "deactivating".to_string(),
+            UnitSubState::Plugged => "plugged".to_string(),
+            UnitSubState::Unknown => "unknown".to_string(),
+        }
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum LoadState {
+    Loaded,
+    NotFound,
+    Error,
     Masked,
 }
 
+impl ToString for LoadState {
+    fn to_string(&self) -> String {
+        match *self {
+            LoadState::Loaded => "loaded".to_string(),
+            LoadState::NotFound => "not found".to_string(),
+            LoadState::Error => "error".to_string(),
+            LoadState::Masked => "maksed".to_string(),
+        }
+    }
+}
+
 //Unit类型
 #[allow(dead_code)]
 #[derive(Clone, Copy, PartialEq, Debug)]
@@ -134,11 +229,15 @@ pub enum UnitType {
 }
 
 //记录unit文件基本信息,这个结构体里面的信息是所有Unit文件都可以有的属性
+#[allow(dead_code)]
 #[derive(Debug, Clone)]
 pub struct BaseUnit {
+    unit_name: String,
     unit_part: UnitPart,
     install_part: InstallPart,
     state: UnitState,
+    sub_state: UnitSubState,
+    load_state: LoadState,
     unit_type: UnitType,
     unit_id: usize,
 }
@@ -146,9 +245,12 @@ pub struct BaseUnit {
 impl Default for BaseUnit {
     fn default() -> Self {
         BaseUnit {
+            unit_name: String::new(),
             unit_part: UnitPart::default(),
             install_part: InstallPart::default(),
-            state: UnitState::Disabled,
+            state: UnitState::Inactive,
+            sub_state: UnitSubState::Unknown,
+            load_state: LoadState::Loaded,
             unit_type: UnitType::Unknown,
             unit_id: 0,
         }
@@ -208,6 +310,22 @@ impl BaseUnit {
     pub fn set_id(&mut self, id: usize) {
         self.unit_id = id;
     }
+
+    pub fn unit_name(&self) -> String {
+        self.unit_name.clone()
+    }
+
+    /// ## Unit基本格式化信息
+    pub fn unit_info(&self) -> String {
+        format!(
+            "{}\t\t\t{}\t\t{}\t\t{}\t\t{}",
+            self.unit_name,
+            self.load_state.to_string(),
+            self.state.to_string(),
+            self.sub_state.to_string(),
+            self.unit_part.description
+        )
+    }
 }
 
 #[derive(Default, Debug, Clone)]

+ 5 - 1
src/unit/service/mod.rs

@@ -176,7 +176,7 @@ impl Unit for ServiceUnit {
         self.exec()
     }
 
-    fn mut_unit_base(&mut self) -> &mut BaseUnit {
+    fn unit_base_mut(&mut self) -> &mut BaseUnit {
         return &mut self.unit_base;
     }
 
@@ -217,6 +217,10 @@ impl Unit for ServiceUnit {
     fn exit(&mut self) {
         ServiceExecutor::exit(self);
     }
+
+    fn restart(&mut self) -> Result<(), RuntimeError> {
+        return ServiceExecutor::restart(self);
+    }
 }
 
 impl ServiceUnit {

+ 1 - 1
src/unit/target/mod.rs

@@ -49,7 +49,7 @@ impl Unit for TargetUnit {
         Ok(())
     }
 
-    fn mut_unit_base(&mut self) -> &mut BaseUnit {
+    fn unit_base_mut(&mut self) -> &mut BaseUnit {
         return &mut self.unit_base;
     }
 

+ 41 - 0
src/unit/timer/mod.rs

@@ -0,0 +1,41 @@
+use super::BaseUnit;
+
+
+pub struct TimerUnit {
+    unit_base: BaseUnit,
+    timer_part: TimerPart,
+}
+
+pub struct TimerPart {
+    on_active_sec: u64,
+    on_boot_sec: u64,
+    on_start_up_sec: u64,
+    on_unit_inactive_sec: u64,
+    on_calendar: u64,
+    accuarcy_sec: u64,
+    randomized_delay_sec: u64,
+    fixed_random_delay: bool,
+    on_clock_change: bool,
+    on_time_zone_change: bool,
+    unit: usize,
+    persistent: bool,
+    wake_system: bool,
+    remain_after_elapse: bool,
+}
+
+pub enum TimerUnitAttr {
+    OnActiveSec,
+    OnBootSec,
+    OnStartUpSec,
+    OnUnitInactiveSec,
+    OnCalendar,
+    AccuarcySec,
+    RandomizedDelaySec,
+    FixedRandomDelay,
+    OnClockChange,
+    OnTimeZoneChange,
+    Unit,
+    Persistent,
+    WakeSystem,
+    RemainAfterElapse,
+}

+ 12 - 0
systemctl/.cargo/config.toml

@@ -0,0 +1,12 @@
+[build]
+target = "../x86_64-unknown-dragonos.json"
+
+[unstable]
+build-std = ["core", "compiler_builtins", "alloc"]
+build-std-features = ["compiler-builtins-mem"]
+
+[target.'cfg(target_os = "dragonos")']
+rustflags = [
+  "-C", "target-feature=+crt-static",
+  "-C", "link-arg=-no-pie",
+]

+ 2 - 0
systemctl/.gitignore

@@ -0,0 +1,2 @@
+/target
+Cargo.lock

+ 17 - 0
systemctl/Cargo.toml

@@ -0,0 +1,17 @@
+[package]
+name = "systemctl"
+version = "0.1.0"
+edition = "2021"
+
+[[bin]]
+name = "systemctl"
+path = "src/main.rs"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+cfg-if = { version = "1.0"}
+
+[target.'cfg(target_os = "dragonos")'.dependencies]
+#drstd = {git = "https://github.com/DragonOS-Community/drstd.git", revision = "af10011"}
+drstd = { path = "/home/heyicong/drstd" }

+ 34 - 0
systemctl/Makefile

@@ -0,0 +1,34 @@
+export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
+export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
+
+OUTPUT_DIR = $(DADK_BUILD_CACHE_DIR_DRAGONREACH_0_1_0)
+REACH_BIN_DIR=$(OUTPUT_DIR)/bin/
+TMP_INSTALL_DIR=$(OUTPUT_DIR)/tmp_install
+
+all: build
+
+build:
+	cargo -Z build-std=core,alloc,compiler_builtins build --target ../x86_64-unknown-dragonos.json --release
+
+install:
+	mkdir -p $(TMP_INSTALL_DIR)
+	mkdir -p $(REACH_BIN_DIR)
+
+	cargo -Z build-std=core,alloc,compiler_builtins install --target $(TARGET) --path .  --root $(TMP_INSTALL_DIR)
+	mv $(TMP_INSTALL_DIR)/bin/systemctl $(REACH_BIN_DIR)/systemctl
+	rm -rf $(TMP_INSTALL_DIR)
+
+build-linux:
+	cargo -Z build-std=core,alloc,compiler_builtins build --target x86_64-unknown-linux-gnu
+
+clean:
+	cargo clean
+
+fmt:
+	cargo fmt
+
+fmt-check:
+	cargo fmt --check
+
+check:
+	cargo -Z build-std=core,alloc,compiler_builtins check --workspace --message-format=json --target ../x86_64-unknown-dragonos.json

+ 74 - 0
systemctl/src/main.rs

@@ -0,0 +1,74 @@
+#![no_std]
+#![no_main]
+
+#[cfg(target_os = "dragonos")]
+extern crate drstd as std;
+
+use std::fs::File;
+use std::libc::c_str::CString;
+use std::os::fd::FromRawFd;
+use std::{env, libc};
+use std::{print, println, string::String, vec::Vec};
+
+const REACH_PIPE_PATH: &str = "/etc/reach/ipc/ctl";
+
+#[cfg(target_os = "dragonos")]
+#[no_mangle]
+fn main() {
+    use std::{
+        eprint, eprintln, format,
+        io::{Read, Write},
+        libc,
+    };
+
+    let mut args: Vec<String> = env::args().collect();
+
+    if args.len() <= 2 {
+        args = Vec::new();
+        args.push(String::from("list-units"));
+    } else {
+        args.remove(0);
+        args.remove(0);
+    }
+
+    let mut msg = String::new();
+    for arg in args {
+        msg = format!("{} {}", msg, arg);
+    }
+
+    if let Err(err) = get_writer().write_all(msg.as_bytes()) {
+        eprintln!("write error {}", err);
+    }
+    // match get_reader().read_to_string(&mut buf) {
+    //     Ok(size) => {
+    //         println!("ctl read size: {}",size);
+    //     },
+    //     Err(err) => {
+    //         eprintln!("read error {}", err);
+    //     },
+    // }
+    // if let Err(err) = get_reader().read_to_string(&mut buf) {
+    //     eprintln!("read error {}", err);
+    // }
+
+    // println!("{}", buf);
+}
+
+#[cfg(not(target_os = "dragonos"))]
+fn main() {}
+
+fn get_writer() -> File {
+    let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_WRONLY) };
+
+    unsafe { File::from_raw_fd(fd) }
+}
+
+fn get_reader() -> File {
+    let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_RDONLY) };
+
+    unsafe { File::from_raw_fd(fd) }
+}
+
+fn ctl_path() -> CString {
+    CString::new(REACH_PIPE_PATH).expect("create pipe path CString error")
+}