#[cfg(unix)]
use std::path::PathBuf;
use crate::AutosshError;
#[cfg(unix)]
pub fn daemonize_unix(
_pidfile: Option<PathBuf>,
logfile: Option<PathBuf>,
) -> Result<(), AutosshError> {
use daemonize::Daemonize;
let mut d = Daemonize::new().working_directory("/").umask(0o027);
if let Some(p) = logfile {
let stdout = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&p)
.map_err(|e| AutosshError::LogfileWrite {
path: p.clone(),
source: e,
})?;
let stderr = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&p)
.map_err(|e| AutosshError::LogfileWrite {
path: p.clone(),
source: e,
})?;
d = d.stdout(stdout).stderr(stderr);
}
d.start().map_err(|e| AutosshError::Daemonize {
reason: e.to_string(),
})
}
#[cfg(windows)]
pub fn detach_windows(
listeners_to_close: Vec<tokio::net::TcpListener>,
) -> Result<(), AutosshError> {
use std::os::windows::ffi::OsStrExt;
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::System::Threading::{
CREATE_NEW_PROCESS_GROUP, CreateProcessW, DETACHED_PROCESS, PROCESS_INFORMATION,
STARTUPINFOW,
};
unsafe {
std::env::set_var("RUSTY_AUTOSSH_DETACHED", "1");
}
drop(listeners_to_close);
let exe = std::env::current_exe().map_err(|e| AutosshError::Daemonize {
reason: format!("current_exe failed: {e}"),
})?;
let mut cmdline_buf: Vec<u16> = Vec::new();
let exe_wide: Vec<u16> = std::ffi::OsStr::new("\"")
.encode_wide()
.chain(exe.as_os_str().encode_wide())
.chain(std::ffi::OsStr::new("\"").encode_wide())
.collect();
cmdline_buf.extend(exe_wide);
for arg in std::env::args_os().skip(1) {
cmdline_buf.push(u16::from(b' '));
cmdline_buf.push(u16::from(b'"'));
for ch in arg.encode_wide() {
cmdline_buf.push(ch);
}
cmdline_buf.push(u16::from(b'"'));
}
cmdline_buf.push(0);
let mut startup: STARTUPINFOW = unsafe { std::mem::zeroed() };
startup.cb = std::mem::size_of::<STARTUPINFOW>() as u32;
let mut info: PROCESS_INFORMATION = unsafe { std::mem::zeroed() };
let ok = unsafe {
CreateProcessW(
std::ptr::null(),
cmdline_buf.as_mut_ptr(),
std::ptr::null(),
std::ptr::null(),
0, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
std::ptr::null(),
std::ptr::null(),
&startup,
&mut info,
)
};
if ok == 0 {
let err = std::io::Error::last_os_error();
return Err(AutosshError::Daemonize {
reason: format!("CreateProcessW failed: {err}"),
});
}
unsafe {
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
}
Ok(())
}