use crate::CoreError;
use crate::error::syscall_ret;
pub enum ForkResult {
Parent(i32),
Child,
}
pub unsafe fn fork() -> Result<ForkResult, CoreError> {
let pid = unsafe { libc::fork() };
if pid < 0 {
return Err(CoreError::sys(
std::io::Error::last_os_error().raw_os_error().unwrap_or(-1),
"fork",
));
}
if pid == 0 {
Ok(ForkResult::Child)
} else {
Ok(ForkResult::Parent(pid))
}
}
pub fn setsid() -> Result<(), CoreError> {
let ret = unsafe { libc::setsid() };
if ret < 0 {
return Err(CoreError::sys(
std::io::Error::last_os_error().raw_os_error().unwrap_or(-1),
"setsid",
));
}
Ok(())
}
pub fn setpgid(pid: i32, pgid: i32) -> Result<(), CoreError> {
syscall_ret(unsafe { libc::setpgid(pid, pgid) }, "setpgid")
}
pub unsafe fn redirect_stdio_to_devnull() -> Result<(), CoreError> {
let fd = unsafe {
libc::open(b"/dev/null\0".as_ptr() as *const libc::c_char,
libc::O_RDWR)
};
if fd < 0 {
return Err(CoreError::sys(
std::io::Error::last_os_error().raw_os_error().unwrap_or(-1),
"open:/dev/null",
));
}
unsafe {
libc::dup2(fd, 0);
libc::dup2(fd, 1);
libc::dup2(fd, 2);
if fd > 2 { libc::close(fd); }
}
Ok(())
}
pub fn set_pdeathsig(sig: i32) -> Result<(), CoreError> {
syscall_ret(
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, sig as libc::c_ulong, 0, 0, 0) },
"prctl:PR_SET_PDEATHSIG",
)
}
pub unsafe fn redirect_fd_to(src_fd: i32, dst_fd: i32) {
unsafe {
libc::dup2(src_fd, dst_fd);
libc::close(src_fd);
}
}
pub fn setuid(uid: u32) -> Result<(), CoreError> {
syscall_ret(
unsafe { libc::setresuid(uid, uid, uid) },
"setresuid",
)
}
pub fn setgid(gid: u32) -> Result<(), CoreError> {
syscall_ret(
unsafe { libc::setresgid(gid, gid, gid) },
"setresgid",
)
}
pub fn close_fds_from(start: i32) {
for fd in start..1024 {
unsafe { libc::close(fd) };
}
}