| 1 | //! Cleanup command - kill stale Wine/WeMod processes |
| 2 | |
| 3 | use clap::Args; |
| 4 | use std::path::PathBuf; |
| 5 | use tokio::process::Command; |
| 6 | use tracing::info; |
| 7 | use wanda_core::error::Result; |
| 8 | |
| 9 | #[derive(Args)] |
| 10 | pub struct CleanupArgs { |
| 11 | /// Force kill without confirmation |
| 12 | #[arg(short, long)] |
| 13 | pub force: bool, |
| 14 | } |
| 15 | |
| 16 | pub async fn run(_args: CleanupArgs, _config_path: Option<PathBuf>) -> Result<()> { |
| 17 | info!("Cleaning up Wine/WeMod processes..."); |
| 18 | |
| 19 | let patterns = [ |
| 20 | "WeMod", |
| 21 | "WeModAuxiliary", |
| 22 | "wineserver", |
| 23 | "winedevice", |
| 24 | "steam.exe", |
| 25 | ]; |
| 26 | |
| 27 | for pattern in &patterns { |
| 28 | let output = Command::new("pkill") |
| 29 | .args(["-9", "-f", pattern]) |
| 30 | .output() |
| 31 | .await; |
| 32 | |
| 33 | match output { |
| 34 | Ok(o) if o.status.success() => { |
| 35 | info!("Killed processes matching '{}'", pattern); |
| 36 | } |
| 37 | _ => {} |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | // Verify cleanup |
| 42 | let check = Command::new("sh") |
| 43 | .args(["-c", "ps aux | grep -iE 'wemod|wineserver|winedevice' | grep -v grep | wc -l"]) |
| 44 | .output() |
| 45 | .await; |
| 46 | |
| 47 | if let Ok(output) = check { |
| 48 | let count: i32 = String::from_utf8_lossy(&output.stdout) |
| 49 | .trim() |
| 50 | .parse() |
| 51 | .unwrap_or(0); |
| 52 | |
| 53 | if count == 0 { |
| 54 | println!("All Wine/WeMod processes cleaned up"); |
| 55 | } else { |
| 56 | println!("{} processes may still be running", count); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | Ok(()) |
| 61 | } |
| 62 |