procutil.rs
104 lines
| 2.8 KiB
| application/rls-services+xml
|
RustLexer
Yuya Nishihara
|
r40006 | // Copyright 2018 Yuya Nishihara <yuya@tcha.org> | ||
// | ||||
// This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | ||||
//! Low-level utility for signal and process handling. | ||||
Yuya Nishihara
|
r40156 | use libc::{self, c_int, pid_t, size_t, ssize_t}; | ||
Yuya Nishihara
|
r40006 | use std::io; | ||
use std::os::unix::io::RawFd; | ||||
Yuya Nishihara
|
r40156 | use std::sync; | ||
Yuya Nishihara
|
r40006 | |||
#[link(name = "procutil", kind = "static")] | ||||
extern "C" { | ||||
// sendfds.c | ||||
fn sendfds(sockfd: c_int, fds: *const c_int, fdlen: size_t) -> ssize_t; | ||||
Yuya Nishihara
|
r40156 | |||
// sighandlers.c | ||||
fn setupsignalhandler(pid: pid_t, pgid: pid_t) -> c_int; | ||||
fn restoresignalhandler() -> c_int; | ||||
Yuya Nishihara
|
r40006 | } | ||
Yuya Nishihara
|
r40012 | /// Returns the effective uid of the current process. | ||
pub fn get_effective_uid() -> u32 { | ||||
unsafe { libc::geteuid() } | ||||
} | ||||
Yuya Nishihara
|
r45174 | /// Returns the umask of the current process. | ||
/// | ||||
/// # Safety | ||||
/// | ||||
/// This is unsafe because the umask value is temporarily changed, and | ||||
/// the change can be observed from the other threads. Don't call this in | ||||
/// multi-threaded context. | ||||
pub unsafe fn get_umask() -> u32 { | ||||
let mask = libc::umask(0); | ||||
libc::umask(mask); | ||||
mask | ||||
} | ||||
Yuya Nishihara
|
r40009 | /// Changes the given fd to blocking mode. | ||
pub fn set_blocking_fd(fd: RawFd) -> io::Result<()> { | ||||
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) }; | ||||
if flags < 0 { | ||||
return Err(io::Error::last_os_error()); | ||||
} | ||||
Martin von Zweigbergk
|
r46195 | let r = | ||
unsafe { libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK) }; | ||||
Yuya Nishihara
|
r40009 | if r < 0 { | ||
Gregory Szorc
|
r44270 | return Err(io::Error::last_os_error()); | ||
Yuya Nishihara
|
r40009 | } | ||
Ok(()) | ||||
} | ||||
Yuya Nishihara
|
r40006 | /// Sends file descriptors via the given socket. | ||
pub fn send_raw_fds(sock_fd: RawFd, fds: &[RawFd]) -> io::Result<()> { | ||||
let r = unsafe { sendfds(sock_fd, fds.as_ptr(), fds.len() as size_t) }; | ||||
if r < 0 { | ||||
return Err(io::Error::last_os_error()); | ||||
} | ||||
Ok(()) | ||||
} | ||||
Yuya Nishihara
|
r40156 | |||
static SETUP_SIGNAL_HANDLER: sync::Once = sync::Once::new(); | ||||
static RESTORE_SIGNAL_HANDLER: sync::Once = sync::Once::new(); | ||||
/// Installs signal handlers to forward signals to the server. | ||||
/// | ||||
/// # Safety | ||||
/// | ||||
/// This touches global states, and thus synchronized as a one-time | ||||
/// initialization function. | ||||
Martin von Zweigbergk
|
r46195 | pub fn setup_signal_handler_once( | ||
pid: u32, | ||||
pgid: Option<u32>, | ||||
) -> io::Result<()> { | ||||
Yuya Nishihara
|
r40156 | let pid_signed = pid as i32; | ||
let pgid_signed = pgid.map(|n| n as i32).unwrap_or(0); | ||||
let mut r = 0; | ||||
SETUP_SIGNAL_HANDLER.call_once(|| { | ||||
r = unsafe { setupsignalhandler(pid_signed, pgid_signed) }; | ||||
}); | ||||
if r < 0 { | ||||
return Err(io::Error::last_os_error()); | ||||
} | ||||
Ok(()) | ||||
} | ||||
/// Restores the original signal handlers. | ||||
/// | ||||
/// # Safety | ||||
/// | ||||
/// This touches global states, and thus synchronized as a one-time | ||||
/// initialization function. | ||||
pub fn restore_signal_handler_once() -> io::Result<()> { | ||||
let mut r = 0; | ||||
RESTORE_SIGNAL_HANDLER.call_once(|| { | ||||
r = unsafe { restoresignalhandler() }; | ||||
}); | ||||
if r < 0 { | ||||
return Err(io::Error::last_os_error()); | ||||
} | ||||
Ok(()) | ||||
} | ||||