From 799b45104ad2b03dac8f16fc4fd3e459f8bedbe0 Mon Sep 17 00:00:00 2001 From: Ferdinand Schober Date: Sun, 12 May 2024 13:01:07 +0200 Subject: [PATCH] enter hook command (#130) new configuration option `enter_hook` can now be used to spawn a command when a client is entered --- Cargo.toml | 2 +- src/client.rs | 3 +++ src/config.rs | 4 ++++ src/server.rs | 1 + src/server/capture_task.rs | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 18bee58..d46900e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ anyhow = "1.0.71" log = "0.4.20" env_logger = "0.11.3" serde_json = "1.0.107" -tokio = {version = "1.32.0", features = ["io-util", "io-std", "macros", "net", "rt", "sync", "signal"] } +tokio = {version = "1.32.0", features = ["io-util", "io-std", "macros", "net", "process", "rt", "sync", "signal"] } async-trait = "0.1.73" futures-core = "0.3.28" futures = "0.3.28" diff --git a/src/client.rs b/src/client.rs index 95b470c..5d70ef5 100644 --- a/src/client.rs +++ b/src/client.rs @@ -102,6 +102,8 @@ pub struct ClientConfig { pub port: u16, /// position of a client on screen pub pos: Position, + /// enter hook + pub cmd: Option, } impl Default for ClientConfig { @@ -111,6 +113,7 @@ impl Default for ClientConfig { hostname: Default::default(), fix_ips: Default::default(), pos: Default::default(), + cmd: None, } } } diff --git a/src/config.rs b/src/config.rs index d5c855f..0878800 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,6 +31,7 @@ pub struct TomlClient { pub ips: Option>, pub port: Option, pub activate_on_startup: Option, + pub enter_hook: Option, } impl ConfigToml { @@ -92,6 +93,7 @@ pub struct ConfigClient { pub port: u16, pub pos: Position, pub active: bool, + pub enter_hook: Option, } const DEFAULT_RELEASE_KEYS: [scancode::Linux; 4] = @@ -208,12 +210,14 @@ impl Config { None => c.host_name.clone(), }; let active = c.activate_on_startup.unwrap_or(false); + let enter_hook = c.enter_hook.clone(); ConfigClient { ips, hostname, port, pos: *pos, active, + enter_hook, } }) .collect() diff --git a/src/server.rs b/src/server.rs index b63db3f..7fc0dbe 100644 --- a/src/server.rs +++ b/src/server.rs @@ -55,6 +55,7 @@ impl Server { fix_ips: config_client.ips.into_iter().collect(), port: config_client.port, pos: config_client.pos, + cmd: config_client.enter_hook, }; let state = ClientState { active: config_client.active, diff --git a/src/server/capture_task.rs b/src/server/capture_task.rs index 4b8c3b0..1f0f409 100644 --- a/src/server/capture_task.rs +++ b/src/server/capture_task.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Result}; use futures::StreamExt; use std::{collections::HashSet, net::SocketAddr}; -use tokio::{sync::mpsc::Sender, task::JoinHandle}; +use tokio::{process::Command, sync::mpsc::Sender, task::JoinHandle}; use crate::{ capture::{self, InputCapture}, @@ -140,6 +140,9 @@ async fn handle_capture_event( if start_timer { let _ = timer_tx.try_send(()); } + if enter { + spawn_hook_command(server, handle); + } if let Some(addr) = addr { if enter { let _ = sender_tx.send((Event::Enter(), addr)).await; @@ -148,3 +151,34 @@ async fn handle_capture_event( } Ok(()) } + +fn spawn_hook_command(server: &Server, handle: ClientHandle) { + let Some(cmd) = server + .client_manager + .borrow() + .get(handle) + .and_then(|(c, _)| c.cmd.clone()) + else { + return; + }; + tokio::task::spawn_local(async move { + log::info!("spawning command!"); + let mut child = match Command::new("sh").arg("-c").arg(cmd.as_str()).spawn() { + Ok(c) => c, + Err(e) => { + log::warn!("could not execute cmd: {e}"); + return; + } + }; + match child.wait().await { + Ok(s) => { + if s.success() { + log::info!("{cmd} exited successfully"); + } else { + log::warn!("{cmd} exited with {s}"); + } + } + Err(e) => log::warn!("{cmd}: {e}"), + } + }); +}