1 use lazy_static::lazy_static; 2 use std::fs::{self, File}; 3 use std::io::Read; 4 use std::os::fd::FromRawFd; 5 use std::string::String; 6 use std::sync::{Arc, Mutex}; 7 use std::vec::Vec; 8 use std::{eprint, eprintln, libc}; 9 10 use crate::error::ErrorFormat; 11 use crate::manager::ctl_manager::CtlManager; 12 13 use super::ctl_parser::{CommandOperation, CtlParser, Pattern}; 14 use super::{ctl_path, DRAGON_REACH_CTL_PIPE}; 15 16 lazy_static! { 17 static ref CTL_READER: Mutex<Arc<File>> = { 18 let file = Systemctl::init_listener(); 19 Mutex::new(Arc::new(file)) 20 }; 21 } 22 23 pub struct Command { 24 pub(crate) operation: CommandOperation, 25 pub(crate) args: Option<Vec<String>>, 26 pub(crate) patterns: Vec<Pattern>, 27 } 28 29 impl Command { 30 #[allow(dead_code)] 31 fn new(op: CommandOperation, patterns: Vec<Pattern>, args: Option<Vec<String>>) -> Self { 32 Command { 33 operation: op, 34 args, 35 patterns: patterns, 36 } 37 } 38 } 39 40 impl Default for Command { 41 fn default() -> Self { 42 Command { 43 operation: CommandOperation::None, 44 args: None, 45 patterns: Vec::new(), 46 } 47 } 48 } 49 50 pub struct Systemctl; 51 52 impl Systemctl { 53 pub fn init() { 54 Self::init_ctl_pipe(); 55 } 56 57 pub fn init_listener() -> File { 58 let fd = unsafe { libc::open(ctl_path().as_ptr(), libc::O_RDONLY | libc::O_NONBLOCK) }; 59 if fd < 0 { 60 panic!("open ctl pipe error"); 61 } 62 unsafe { File::from_raw_fd(fd) } 63 } 64 65 pub fn ctl_listen() { 66 let mut guard = CTL_READER.lock().unwrap(); 67 let mut s = String::new(); 68 if let Ok(size) = guard.read_to_string(&mut s) { 69 if size == 0 { 70 return; 71 } 72 match CtlParser::parse_ctl(&s) { 73 Ok(cmd) => { 74 let _ = CtlManager::exec_ctl(cmd); 75 } 76 Err(err) => { 77 eprintln!("parse tcl command error: {}", err.error_format()); 78 } 79 } 80 } 81 } 82 83 fn is_ctl_exists() -> bool { 84 if let Ok(metadata) = fs::metadata(DRAGON_REACH_CTL_PIPE) { 85 metadata.is_file() 86 } else { 87 false 88 } 89 } 90 91 fn init_ctl_pipe() { 92 if !Self::is_ctl_exists() { 93 let path = ctl_path(); 94 let ret = unsafe { libc::mkfifo(path.as_ptr(), 0o666) }; 95 if ret != 0 { 96 // 创建管道失败打日志 97 panic!("create ctl pipe failed"); 98 } 99 } 100 } 101 } 102