#[cfg(unix)]
pub fn exec_reload(
raw_fd: std::os::unix::io::RawFd,
nick: &str,
server: &str,
channels: &[String],
keepalive_interval_ms: u64,
keepalive_timeout_ms: u64,
) -> crate::BoxError {
use std::os::unix::process::CommandExt;
let flags = unsafe { libc::fcntl(raw_fd, libc::F_GETFD) };
if flags == -1 {
return format!("fcntl(F_GETFD) failed: {}", std::io::Error::last_os_error()).into();
}
let rc = unsafe { libc::fcntl(raw_fd, libc::F_SETFD, flags & !libc::FD_CLOEXEC) };
if rc == -1 {
return format!("fcntl(F_SETFD) failed: {}", std::io::Error::last_os_error()).into();
}
let exe = match std::env::current_exe() {
Ok(p) => p,
Err(e) => return Box::new(e),
};
let mut cmd = std::process::Command::new(&exe);
cmd.env(ENV_FD, raw_fd.to_string())
.env(ENV_NICK, nick)
.env(ENV_SERVER, server)
.env(ENV_CHANNELS, channels.join(","))
.env(ENV_KA_INTERVAL, keepalive_interval_ms.to_string())
.env(ENV_KA_TIMEOUT, keepalive_timeout_ms.to_string());
if let Some((burst, rate_ms)) = FLOOD_FOR_RELOAD.get() {
cmd.env(ENV_FLOOD_BURST, burst.to_string())
.env(ENV_FLOOD_RATE, rate_ms.to_string());
}
let err = cmd.exec();
Box::new(err)
}
#[cfg(unix)]
pub fn record_flood_settings(burst: usize, rate_ms: u64) {
let _ = FLOOD_FOR_RELOAD.set((burst, rate_ms));
}
#[cfg(unix)]
static FLOOD_FOR_RELOAD: std::sync::OnceLock<(usize, u64)> = std::sync::OnceLock::new();
pub const ENV_FD: &str = "IRCBOT_INHERIT_FD";
pub const ENV_NICK: &str = "IRCBOT_NICK";
pub const ENV_SERVER: &str = "IRCBOT_SERVER";
pub const ENV_CHANNELS: &str = "IRCBOT_CHANNELS";
pub const ENV_KA_INTERVAL: &str = "IRCBOT_KEEPALIVE_INTERVAL_MS";
pub const ENV_KA_TIMEOUT: &str = "IRCBOT_KEEPALIVE_TIMEOUT_MS";
pub const ENV_FLOOD_BURST: &str = "IRCBOT_FLOOD_BURST";
pub const ENV_FLOOD_RATE: &str = "IRCBOT_FLOOD_RATE_MS";