use std::process::Stdio; use tauri::{AppHandle, Emitter}; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::process::Command; #[tauri::command] pub async fn run_traceroute(app: AppHandle, ip: String) -> Result<(), String> { let _ = app.emit("traceroute:start", &ip); #[cfg(target_os = "linux")] let mut child = Command::new("tracepath") .arg("-b") .arg(&ip) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() .map_err(|e| { format!( "Failed to start tracepath: {}. Is iputils-tracepath installed?", e ) })?; #[cfg(target_os = "windows")] let mut child = { use std::os::windows::process::CommandExt; const CREATE_NO_WINDOW: u32 = 0x08000000; Command::new("tracert") .arg("-d") .arg(&ip) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .creation_flags(CREATE_NO_WINDOW) .spawn() .map_err(|e| format!("Failed to start tracert: {}", e))? }; let stdout = child .stdout .take() .ok_or_else(|| "Failed to capture stdout".to_string())?; let mut reader = BufReader::new(stdout).lines(); while let Ok(Some(line)) = reader.next_line().await { let _ = app.emit("traceroute:hop", &line); } let status = child .wait() .await .map_err(|e| format!("tracepath failed: {}", e))?; if status.success() { let _ = app.emit("traceroute:complete", &ip); } else { let _ = app.emit("traceroute:error", "tracepath exited with an error"); } Ok(()) }