xref: /DragonReach/src/systemctl/listener/mod.rs (revision 2069cc0dc0984a2981454b00316ba607f88ac512)
1909e4d10SGnoCiYeH use std::fs::{self, File};
2909e4d10SGnoCiYeH use std::io::Read;
3909e4d10SGnoCiYeH use std::os::fd::FromRawFd;
4909e4d10SGnoCiYeH use std::sync::{Arc, Mutex};
5dfd3fd98S裕依2439 
6dfd3fd98S裕依2439 use lazy_static::lazy_static;
7909e4d10SGnoCiYeH 
8909e4d10SGnoCiYeH use crate::error::ErrorFormat;
9909e4d10SGnoCiYeH use crate::manager::ctl_manager::CtlManager;
10909e4d10SGnoCiYeH 
11909e4d10SGnoCiYeH use super::ctl_parser::{CommandOperation, CtlParser, Pattern};
12909e4d10SGnoCiYeH use super::{ctl_path, DRAGON_REACH_CTL_PIPE};
13909e4d10SGnoCiYeH 
14909e4d10SGnoCiYeH lazy_static! {
15909e4d10SGnoCiYeH     static ref CTL_READER: Mutex<Arc<File>> = {
16909e4d10SGnoCiYeH         let file = Systemctl::init_listener();
17909e4d10SGnoCiYeH         Mutex::new(Arc::new(file))
18909e4d10SGnoCiYeH     };
19909e4d10SGnoCiYeH }
20909e4d10SGnoCiYeH 
21909e4d10SGnoCiYeH pub struct Command {
22909e4d10SGnoCiYeH     pub(crate) operation: CommandOperation,
23909e4d10SGnoCiYeH     pub(crate) args: Option<Vec<String>>,
24909e4d10SGnoCiYeH     pub(crate) patterns: Vec<Pattern>,
25909e4d10SGnoCiYeH }
26909e4d10SGnoCiYeH 
27909e4d10SGnoCiYeH impl Command {
28909e4d10SGnoCiYeH     #[allow(dead_code)]
new(op: CommandOperation, patterns: Vec<Pattern>, args: Option<Vec<String>>) -> Self29909e4d10SGnoCiYeH     fn new(op: CommandOperation, patterns: Vec<Pattern>, args: Option<Vec<String>>) -> Self {
30909e4d10SGnoCiYeH         Command {
31909e4d10SGnoCiYeH             operation: op,
32909e4d10SGnoCiYeH             args,
33909e4d10SGnoCiYeH             patterns: patterns,
34909e4d10SGnoCiYeH         }
35909e4d10SGnoCiYeH     }
36909e4d10SGnoCiYeH }
37909e4d10SGnoCiYeH 
38909e4d10SGnoCiYeH impl Default for Command {
default() -> Self39909e4d10SGnoCiYeH     fn default() -> Self {
40909e4d10SGnoCiYeH         Command {
41909e4d10SGnoCiYeH             operation: CommandOperation::None,
42909e4d10SGnoCiYeH             args: None,
43909e4d10SGnoCiYeH             patterns: Vec::new(),
44909e4d10SGnoCiYeH         }
45909e4d10SGnoCiYeH     }
46909e4d10SGnoCiYeH }
47909e4d10SGnoCiYeH 
48909e4d10SGnoCiYeH pub struct Systemctl;
49909e4d10SGnoCiYeH 
50909e4d10SGnoCiYeH impl Systemctl {
51*2069cc0dSBrahmaMantra     /// # 初始化系统服务控制 - 初始化系统服务控制管道
init()52909e4d10SGnoCiYeH     pub fn init() {
53909e4d10SGnoCiYeH         Self::init_ctl_pipe();
54909e4d10SGnoCiYeH     }
55*2069cc0dSBrahmaMantra     /// # 初始化监听器 - 初始化系统服务控制命令监听器
56*2069cc0dSBrahmaMantra     ///
57*2069cc0dSBrahmaMantra     /// 打开系统服务控制命令的管道文件描述符,并设置为非阻塞模式。
58*2069cc0dSBrahmaMantra     ///
init_listener() -> File59909e4d10SGnoCiYeH     pub fn init_listener() -> File {
60909e4d10SGnoCiYeH         let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_RDONLY | libc::O_NONBLOCK) };
61909e4d10SGnoCiYeH         if fd < 0 {
62909e4d10SGnoCiYeH             panic!("open ctl pipe error");
63909e4d10SGnoCiYeH         }
64909e4d10SGnoCiYeH         unsafe { File::from_raw_fd(fd) }
65909e4d10SGnoCiYeH     }
66*2069cc0dSBrahmaMantra     /// # 监听控制命令 - 监听系统服务控制命令
67*2069cc0dSBrahmaMantra     ///
68*2069cc0dSBrahmaMantra     /// 持续从系统服务控制管道中读取命令。
69*2069cc0dSBrahmaMantra     ///
ctl_listen()70909e4d10SGnoCiYeH     pub fn ctl_listen() {
71909e4d10SGnoCiYeH         let mut guard = CTL_READER.lock().unwrap();
72909e4d10SGnoCiYeH         let mut s = String::new();
73909e4d10SGnoCiYeH         if let Ok(size) = guard.read_to_string(&mut s) {
74909e4d10SGnoCiYeH             if size == 0 {
75909e4d10SGnoCiYeH                 return;
76909e4d10SGnoCiYeH             }
77909e4d10SGnoCiYeH             match CtlParser::parse_ctl(&s) {
78909e4d10SGnoCiYeH                 Ok(cmd) => {
79909e4d10SGnoCiYeH                     let _ = CtlManager::exec_ctl(cmd);
80909e4d10SGnoCiYeH                 }
81909e4d10SGnoCiYeH                 Err(err) => {
82909e4d10SGnoCiYeH                     eprintln!("parse tcl command error: {}", err.error_format());
83909e4d10SGnoCiYeH                 }
84909e4d10SGnoCiYeH             }
85909e4d10SGnoCiYeH         }
86909e4d10SGnoCiYeH     }
87909e4d10SGnoCiYeH 
88*2069cc0dSBrahmaMantra     /// # 检查控制管道是否存在 - 检查系统服务控制管道文件是否存在
89*2069cc0dSBrahmaMantra     ///
90*2069cc0dSBrahmaMantra     /// 返回管道文件是否存在。
91*2069cc0dSBrahmaMantra     ///
is_ctl_exists() -> bool92909e4d10SGnoCiYeH     fn is_ctl_exists() -> bool {
93909e4d10SGnoCiYeH         if let Ok(metadata) = fs::metadata(DRAGON_REACH_CTL_PIPE) {
94909e4d10SGnoCiYeH             metadata.is_file()
95909e4d10SGnoCiYeH         } else {
96909e4d10SGnoCiYeH             false
97909e4d10SGnoCiYeH         }
98909e4d10SGnoCiYeH     }
99909e4d10SGnoCiYeH 
init_ctl_pipe()100909e4d10SGnoCiYeH     fn init_ctl_pipe() {
101909e4d10SGnoCiYeH         if !Self::is_ctl_exists() {
102909e4d10SGnoCiYeH             let path = ctl_path();
103909e4d10SGnoCiYeH             let ret = unsafe { libc::mkfifo(path.as_ptr(), 0o666) };
104909e4d10SGnoCiYeH             if ret != 0 {
105909e4d10SGnoCiYeH                 // 创建管道失败打日志
1067c7ad4f0SLoGin                 panic!("create ctl pipe failed, err: {ret}");
107909e4d10SGnoCiYeH             }
108909e4d10SGnoCiYeH         }
109909e4d10SGnoCiYeH     }
110909e4d10SGnoCiYeH }
111