#[cfg(unix)]
pub fn daemonize() -> Result<(), Box<dyn std::error::Error>> {
use std::ffi::CString;
let pid = unsafe { libc::fork() };
if pid < 0 {
return Err(format!("first fork failed: {}", std::io::Error::last_os_error()).into());
}
if pid > 0 {
unsafe { libc::_exit(0) };
}
if unsafe { libc::setsid() } < 0 {
return Err(format!("setsid failed: {}", std::io::Error::last_os_error()).into());
}
let pid = unsafe { libc::fork() };
if pid < 0 {
return Err(format!("second fork failed: {}", std::io::Error::last_os_error()).into());
}
if pid > 0 {
unsafe { libc::_exit(0) };
}
unsafe { libc::umask(0o027) };
let devnull_path = CString::new("/dev/null").unwrap();
let devnull_fd = unsafe { libc::open(devnull_path.as_ptr(), libc::O_RDWR) };
if devnull_fd < 0 {
return Err(format!(
"failed to open /dev/null: {}",
std::io::Error::last_os_error()
)
.into());
}
for fd in 0..=2 {
if unsafe { libc::dup2(devnull_fd, fd) } < 0 {
return Err(format!(
"dup2 to fd {} failed: {}",
fd,
std::io::Error::last_os_error()
)
.into());
}
}
if devnull_fd > 2 {
unsafe { libc::close(devnull_fd) };
}
Ok(())
}