//! SAS Client - Named pipe client for communicating with GuruConnect SAS Service //! //! The SAS Service runs as SYSTEM and handles Ctrl+Alt+Del requests. //! This client sends commands to the service via named pipe. use std::fs::OpenOptions; use std::io::{Read, Write}; use std::time::Duration; use anyhow::{Context, Result}; use tracing::{debug, error, info, warn}; const PIPE_NAME: &str = r"\\.\pipe\guruconnect-sas"; const TIMEOUT_MS: u64 = 5000; /// Request Ctrl+Alt+Del (Secure Attention Sequence) via the SAS service pub fn request_sas() -> Result<()> { info!("Requesting SAS via service pipe..."); // Try to connect to the pipe let mut pipe = match OpenOptions::new() .read(true) .write(true) .open(PIPE_NAME) { Ok(p) => p, Err(e) => { warn!("Failed to connect to SAS service pipe: {}", e); return Err(anyhow::anyhow!( "SAS service not available. Install with: guruconnect-sas-service install" )); } }; debug!("Connected to SAS service pipe"); // Send the command pipe.write_all(b"sas\n") .context("Failed to send command to SAS service")?; // Read the response let mut response = [0u8; 64]; let n = pipe.read(&mut response) .context("Failed to read response from SAS service")?; let response_str = String::from_utf8_lossy(&response[..n]); let response_str = response_str.trim(); debug!("SAS service response: {}", response_str); match response_str { "ok" => { info!("SAS request successful"); Ok(()) } "error" => { error!("SAS service reported an error"); Err(anyhow::anyhow!("SAS service failed to send Ctrl+Alt+Del")) } _ => { error!("Unexpected response from SAS service: {}", response_str); Err(anyhow::anyhow!("Unexpected SAS service response: {}", response_str)) } } } /// Check if the SAS service is available pub fn is_service_available() -> bool { // Try to open the pipe if let Ok(mut pipe) = OpenOptions::new() .read(true) .write(true) .open(PIPE_NAME) { // Send a ping command if pipe.write_all(b"ping\n").is_ok() { let mut response = [0u8; 64]; if let Ok(n) = pipe.read(&mut response) { let response_str = String::from_utf8_lossy(&response[..n]); return response_str.trim() == "pong"; } } } false } /// Get information about SAS service status pub fn get_service_status() -> String { if is_service_available() { "SAS service is running and responding".to_string() } else { "SAS service is not available".to_string() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_service_check() { // This test just checks the function runs without panicking let available = is_service_available(); println!("SAS service available: {}", available); } }