use std::fs;
use std::io::{self, ErrorKind};
use std::path::PathBuf;
pub fn get_pid_file() -> PathBuf {
let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
home.join(".claude-code-mux").join("ccm.pid")
}
pub fn write_pid() -> io::Result<()> {
let pid_file = get_pid_file();
if let Some(parent) = pid_file.parent() {
fs::create_dir_all(parent)?;
}
let pid = std::process::id();
fs::write(&pid_file, pid.to_string())?;
tracing::info!("PID {} written to {:?}", pid, pid_file);
Ok(())
}
pub fn read_pid() -> io::Result<u32> {
let pid_file = get_pid_file();
let pid_str = fs::read_to_string(&pid_file)?;
pid_str.trim().parse::<u32>()
.map_err(|e| io::Error::new(ErrorKind::InvalidData, e))
}
pub fn cleanup_pid() -> io::Result<()> {
let pid_file = get_pid_file();
if pid_file.exists() {
fs::remove_file(&pid_file)?;
tracing::info!("PID file removed: {:?}", pid_file);
}
Ok(())
}
#[cfg(unix)]
pub fn is_process_running(pid: u32) -> bool {
use nix::sys::signal::{kill, Signal};
use nix::unistd::Pid;
match kill(Pid::from_raw(pid as i32), Signal::SIGCONT) {
Ok(_) => true,
Err(_) => false,
}
}
#[cfg(windows)]
pub fn is_process_running(pid: u32) -> bool {
use std::process::Command;
Command::new("tasklist")
.args(&["/FI", &format!("PID eq {}", pid)])
.output()
.ok()
.and_then(|output| {
String::from_utf8(output.stdout)
.ok()
.map(|s| s.contains(&pid.to_string()))
})
.unwrap_or(false)
}