pub mod fork;
pub mod ipc;
pub mod server;
use crate::config;
use std::{fs, thread, time::Duration};
pub fn is_running() -> bool {
let cfg = config::get();
let pid_str = match fs::read_to_string(&cfg.pid_path) {
Ok(s) => s,
Err(_) => return false,
};
let pid: libc::pid_t = match pid_str.trim().parse() {
Ok(p) => p,
Err(_) => return false,
};
if pid <= 0 {
return false;
}
unsafe { libc::kill(pid, 0) == 0 }
}
pub fn ensure_running() {
if is_running() {
return;
}
fork::spawn_daemon(|| server::run());
let cfg = config::get();
for _ in 0..30 {
thread::sleep(Duration::from_millis(100));
if cfg.sock_path.exists() {
return;
}
}
eprintln!(
"error: daemon did not start within 3 seconds \
(socket {:?} never appeared)",
cfg.sock_path
);
std::process::exit(1);
}
pub fn start_cmd() {
config::init();
if is_running() {
let pid = read_pid().unwrap_or(0);
println!("Daemon is already running (pid {}).", pid);
return;
}
println!("Starting daemon…");
fork::spawn_daemon(|| server::run());
let cfg = config::get();
for _ in 0..30 {
thread::sleep(Duration::from_millis(100));
if cfg.sock_path.exists() {
let pid = read_pid().unwrap_or(0);
println!("Daemon started (pid {}).", pid);
return;
}
}
eprintln!(
"error: daemon did not start within 3 seconds \
(socket {:?} never appeared)",
cfg.sock_path
);
std::process::exit(1);
}
pub fn stop_cmd() {
config::init();
let pid: libc::pid_t = match read_pid() {
Some(p) => p,
None => {
println!("Daemon is not running (no PID file).");
return;
}
};
if unsafe { libc::kill(pid, 0) } != 0 {
println!("Daemon is not running (pid {} not found).", pid);
cleanup_files();
return;
}
println!("Stopping daemon (pid {})…", pid);
unsafe { libc::kill(pid, libc::SIGTERM) };
for _ in 0..20 {
thread::sleep(Duration::from_millis(100));
if unsafe { libc::kill(pid, 0) } != 0 {
break;
}
}
cleanup_files();
println!("Daemon stopped.");
}
pub fn status_cmd() {
config::init();
match read_pid() {
None => println!("Daemon: stopped (no PID file)"),
Some(pid) => {
if unsafe { libc::kill(pid, 0) } == 0 {
println!("Daemon: running (pid {})", pid);
} else {
println!("Daemon: stopped (pid {} not found)", pid);
cleanup_files();
}
}
}
}
fn read_pid() -> Option<libc::pid_t> {
let cfg = config::get();
let content = fs::read_to_string(&cfg.pid_path).ok()?;
content.trim().parse::<libc::pid_t>().ok()
}
fn cleanup_files() {
let cfg = config::get();
let _ = fs::remove_file(&cfg.pid_path);
let _ = fs::remove_file(&cfg.sock_path);
}