From 35d4960d87b8e2ac6e8a32fd642b1f7555f3ec2a Mon Sep 17 00:00:00 2001 From: Shinyzenith Date: Thu, 3 Feb 2022 20:23:21 +0530 Subject: [PATCH] [refactor] Simple IPC implementation using std::os --- src/daemon.rs | 14 +++++++- src/server.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/server.rs diff --git a/src/daemon.rs b/src/daemon.rs index bf13207..fcf2154 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,7 +1,7 @@ use clap::{arg, App}; use evdev::{Device, Key}; use nix::unistd; -use std::{env, path::Path, process::exit}; +use std::{env, io::prelude::*, os::unix::net::UnixStream, path::Path, process::exit}; pub fn main() { let args = set_flags().get_matches(); @@ -41,6 +41,12 @@ pub fn main() { exit(1); } log::debug!("{} Keyboard device(s) detected.", keyboard_devices.len()); + match sock_send("notify-send hello world") { + Err(e) => { + log::error!("Failed to send command over IPC: {:#?}", e); + } + _ => {} + }; } pub fn permission_check() { @@ -108,3 +114,9 @@ pub fn check_config_xdg() -> std::path::PathBuf { } config_file_path } + +fn sock_send(command: &str) -> std::io::Result<()> { + let mut stream = UnixStream::connect("/tmp/swhkd.sock")?; + stream.write_all(command.as_bytes())?; + Ok(()) +} diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..b91d862 --- /dev/null +++ b/src/server.rs @@ -0,0 +1,91 @@ +use std::io::prelude::*; +use std::os::unix::net::UnixListener; +use std::{ + env, fs, + path::Path, + process::{exit, id, Command, Stdio}, +}; +use sysinfo::{ProcessExt, System, SystemExt}; + +fn main() -> std::io::Result<()> { + env::set_var("RUST_LOG", "swhks=trace"); + env_logger::init(); + + let pidfile: String = String::from("/tmp/swhkc.pid"); + let sockfile: String = String::from("/tmp/swhkd.sock"); + + if Path::new(&pidfile).exists() { + log::trace!("Reading {} file and checking for running instances.", pidfile); + let swhkd_pid = match fs::read_to_string(&pidfile) { + Ok(swhkd_pid) => swhkd_pid, + Err(e) => { + log::error!("Unable to read {} to check all running instances", e); + exit(1); + } + }; + log::debug!("Previous PID: {}", swhkd_pid); + + let mut sys = System::new_all(); + sys.refresh_all(); + for (pid, process) in sys.processes() { + if pid.to_string() == swhkd_pid { + if process.exe() == env::current_exe().unwrap() { + log::error!("Server is already running!"); + exit(1); + } + } + } + } + + if Path::new(&sockfile).exists() { + log::trace!("Sockfile exists, attempting to remove it."); + match fs::remove_file(&sockfile) { + Ok(_) => { + log::debug!("Removed old socket file"); + } + Err(e) => { + log::error!("Error removing the socket file!: {}", e); + log::error!("You can manually remove the socket file: {}", sockfile); + exit(1); + } + }; + } + + match fs::write(&pidfile, id().to_string()) { + Ok(_) => {} + Err(e) => { + log::error!("Unable to write to {}: {}", pidfile, e); + exit(1); + } + } + + fn run_system_command(command: &String) -> () { + match Command::new("sh") + .arg("-c") + .arg(command) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + { + Ok(_) => {} + Err(e) => { + log::error!("Failed to execute {}", command); + log::error!("Error, {}", e); + } + } + } + + let listener = UnixListener::bind(sockfile)?; + loop { + match listener.accept() { + Ok((mut socket, addr)) => { + let mut response = String::new(); + socket.read_to_string(&mut response)?; + run_system_command(&response); + log::debug!("Socket: {:?} Address: {:?} Response: {}", socket, addr, response); + } + Err(e) => log::error!("accept function failed: {:?}", e), + } + } +}