391 lines
9.6 KiB
Rust
391 lines
9.6 KiB
Rust
use core::{
|
|
ffi::{c_char, c_int, c_long, c_void, CStr},
|
|
ptr::NonNull,
|
|
};
|
|
|
|
use yggdrasil_rt::process::{signal as rt, Signal};
|
|
|
|
use crate::{
|
|
error::{self, CIntZeroResult, CResult, EResult},
|
|
headers::errno::Errno,
|
|
signal,
|
|
util::PointerExt,
|
|
};
|
|
|
|
use super::{
|
|
sys_time::__ygg_timespec_t,
|
|
sys_types::{pid_t, uid_t},
|
|
};
|
|
|
|
pub type sig_handler_t = unsafe extern "C" fn(c_int);
|
|
|
|
pub type sigset_t = u64;
|
|
|
|
#[repr(C)]
|
|
pub struct stack_t {
|
|
pub ss_sp: *mut c_void,
|
|
pub ss_flags: c_int,
|
|
pub ss_size: usize,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct sigevent {
|
|
pub sigev_notify: c_int,
|
|
pub sigev_signo: c_int,
|
|
pub sigev_value: sigval,
|
|
pub sigev_notify_function: unsafe extern "C" fn(sigval),
|
|
// TODO pthread_attr_t *
|
|
pub sigev_notify_attributes: *mut c_void,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct sigaction {
|
|
pub sa_handler: unsafe extern "C" fn(c_int),
|
|
pub sa_mask: sigset_t,
|
|
pub sa_flags: c_int,
|
|
pub sa_sigaction: unsafe extern "C" fn(c_int, *mut siginfo_t, *mut c_void),
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct siginfo {
|
|
pub si_signo: c_int,
|
|
pub si_code: c_int,
|
|
pub si_errno: c_int,
|
|
pub si_pid: pid_t,
|
|
pub si_uid: uid_t,
|
|
pub si_addr: *mut c_void,
|
|
pub si_status: c_int,
|
|
pub si_band: c_long,
|
|
pub si_value: sigval,
|
|
}
|
|
|
|
pub type siginfo_t = siginfo;
|
|
|
|
#[repr(C)]
|
|
pub union sigval {
|
|
pub sival_int: c_int,
|
|
pub sival_ptr: *mut c_void,
|
|
}
|
|
|
|
// TODO sig_atomic_t
|
|
|
|
// SIG_DFL, SIG_ERR, SIG_HOLD, SIG_IGN are in <bits/signal.h>
|
|
|
|
extern "C" {
|
|
fn __sig_terminate(_: c_int);
|
|
fn __sig_ignore(_: c_int);
|
|
}
|
|
|
|
pub const SIGHUP: c_int = 1;
|
|
pub const SIGINT: c_int = 2;
|
|
pub const SIGQUIT: c_int = 3;
|
|
pub const SIGILL: c_int = 4;
|
|
pub const SIGTRAP: c_int = 5;
|
|
pub const SIGABRT: c_int = 6;
|
|
pub const SIGBUS: c_int = 7;
|
|
pub const SIGFPE: c_int = 8;
|
|
pub const SIGKILL: c_int = 9;
|
|
pub const SIGUSR1: c_int = 10;
|
|
pub const SIGSEGV: c_int = 11;
|
|
pub const SIGUSR2: c_int = 12;
|
|
pub const SIGPIPE: c_int = 13;
|
|
pub const SIGALRM: c_int = 14;
|
|
pub const SIGTERM: c_int = 15;
|
|
pub const SIGCHLD: c_int = 17;
|
|
pub const SIGCONT: c_int = 18;
|
|
pub const SIGSTOP: c_int = 19;
|
|
pub const SIGTSTP: c_int = 20;
|
|
pub const SIGTTIN: c_int = 21;
|
|
pub const SIGTTOU: c_int = 22;
|
|
pub const SIGURG: c_int = 23;
|
|
pub const SIGXCPU: c_int = 24;
|
|
pub const SIGXFSZ: c_int = 25;
|
|
pub const SIGVTALRM: c_int = 26;
|
|
pub const SIGPROF: c_int = 27;
|
|
pub const SIGWINCH: c_int = 28;
|
|
pub const SIGPOLL: c_int = 29;
|
|
pub const SIGPWR: c_int = 30;
|
|
pub const SIGSYS: c_int = 31;
|
|
pub const SIGNAL_MAX: c_int = SIGSYS + 1;
|
|
|
|
pub const SIGEV_NONE: c_int = 0;
|
|
pub const SIGEV_SIGNAL: c_int = 1;
|
|
pub const SIGEV_THREAD: c_int = 2;
|
|
|
|
pub const SIG_BLOCK: c_int = 1;
|
|
pub const SIG_UNBLOCK: c_int = 2;
|
|
pub const SIG_SETMASK: c_int = 3;
|
|
|
|
pub const SA_NOCLDSTOP: c_int = 1 << 0;
|
|
pub const SA_ONSTACK: c_int = 1 << 2;
|
|
pub const SA_RESETHAND: c_int = 1 << 3;
|
|
pub const SA_RESTART: c_int = 1 << 4;
|
|
pub const SA_SIGINFO: c_int = 1 << 5;
|
|
pub const SA_NOCLDWAIT: c_int = 1 << 6;
|
|
pub const SA_NODEFER: c_int = 1 << 7;
|
|
|
|
pub const SS_ONSTACK: c_int = 1 << 8;
|
|
pub const SS_DISABLE: c_int = 1 << 9;
|
|
|
|
pub const MINSIGSTKSZ: usize = 2 * 4096;
|
|
pub const SIGSTKSZ: usize = 8 * 4096;
|
|
|
|
pub fn int_to_signum(value: c_int) -> EResult<Signal> {
|
|
match value {
|
|
SIGABRT => EResult::Ok(Signal::Aborted),
|
|
SIGSEGV => EResult::Ok(Signal::MemoryAccessViolation),
|
|
SIGINT => EResult::Ok(Signal::Interrupted),
|
|
SIGILL => EResult::Ok(Signal::InvalidInstruction),
|
|
SIGKILL => EResult::Ok(Signal::Killed),
|
|
SIGTERM => EResult::Ok(Signal::Terminated),
|
|
_ => EResult::Err(Errno::EINVAL),
|
|
}
|
|
}
|
|
|
|
pub fn signum_to_int(value: Signal) -> c_int {
|
|
match value {
|
|
Signal::Aborted => SIGABRT,
|
|
Signal::MemoryAccessViolation => SIGSEGV,
|
|
Signal::Interrupted => SIGINT,
|
|
Signal::InvalidInstruction => SIGILL,
|
|
Signal::Killed => SIGKILL,
|
|
Signal::Terminated => SIGTERM,
|
|
// Never issued/handled
|
|
Signal::Debug => unreachable!(),
|
|
}
|
|
}
|
|
|
|
pub fn signal_string(value: c_int) -> Option<&'static CStr> {
|
|
match value {
|
|
SIGHUP => Some(c"Hangup"),
|
|
SIGINT => Some(c"Interrupted"),
|
|
SIGQUIT => Some(c"Quit"),
|
|
SIGILL => Some(c"Illegal instruction"),
|
|
SIGTRAP => Some(c"Trap/breakpoint"),
|
|
SIGABRT => Some(c"Aborted"),
|
|
SIGBUS => Some(c"Bus error"),
|
|
SIGFPE => Some(c"Floating-point exception"),
|
|
SIGKILL => Some(c"Killed"),
|
|
SIGUSR1 => Some(c"User signal 1"),
|
|
SIGSEGV => Some(c"Segmentation fault"),
|
|
SIGUSR2 => Some(c"User signal 2"),
|
|
SIGPIPE => Some(c"Broken pipe"),
|
|
SIGALRM => Some(c"Timer alarm"),
|
|
SIGTERM => Some(c"Terminated"),
|
|
SIGCHLD => Some(c"Child quit"),
|
|
SIGCONT => Some(c"Continued"),
|
|
SIGSTOP => Some(c"Stopped"),
|
|
SIGTSTP => Some(c"Terminal stopped"),
|
|
SIGTTIN => Some(c"Background process terminal input"),
|
|
SIGTTOU => Some(c"Background process terminal output"),
|
|
SIGURG => Some(c"Urgent"),
|
|
SIGXCPU => Some(c"CPU time limit exceeded"),
|
|
SIGXFSZ => Some(c"File size limit exceeded"),
|
|
SIGVTALRM => Some(c"Virtual alarm"),
|
|
SIGPROF => Some(c"Profiling timer expired"),
|
|
SIGWINCH => Some(c"Window size changed"),
|
|
SIGPOLL => Some(c"Pollable event"),
|
|
SIGPWR => Some(c"Power failure"),
|
|
SIGSYS => Some(c"Bad system call"),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn kill(_pid: pid_t, _signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn killpg(_pgid: pid_t, _signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn psiginfo(_info: *const siginfo_t, _m: *const c_char) {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn psignal(_signum: c_int, _m: *const c_char) {
|
|
todo!()
|
|
}
|
|
|
|
// TODO pthread_t
|
|
#[no_mangle]
|
|
unsafe extern "C" fn pthread_kill(_pt: *mut c_void, _signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn pthread_sigmask(
|
|
_a: c_int,
|
|
_new: *const sigset_t,
|
|
_old: *mut sigset_t,
|
|
) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn raise(_signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigaction(
|
|
signum: c_int,
|
|
_new: *const sigaction,
|
|
_old: *mut sigaction,
|
|
) -> CIntZeroResult {
|
|
log::error!("TODO: sigaction({:?})", signum);
|
|
CIntZeroResult::SUCCESS
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigaddset(mask: *mut sigset_t, signum: c_int) -> CIntZeroResult {
|
|
if signum > 63 || signum <= 0 {
|
|
error::errno = Errno::EINVAL;
|
|
return CIntZeroResult::ERROR;
|
|
}
|
|
*mask |= 1 << signum;
|
|
CIntZeroResult::SUCCESS
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigaltstack(new: *const stack_t, old: *mut stack_t) -> CIntZeroResult {
|
|
if let Some(old) = NonNull::new(old) {
|
|
let (base, size) = rt::get_signal_stack();
|
|
old.write(stack_t {
|
|
ss_sp: base as _,
|
|
ss_flags: 0,
|
|
ss_size: size,
|
|
});
|
|
}
|
|
if let Some(new) = new.as_ref() {
|
|
// TODO what do with SS_DISABLE?
|
|
if new.ss_size < MINSIGSTKSZ {
|
|
error::errno = Errno::ENOMEM;
|
|
return CIntZeroResult::ERROR;
|
|
}
|
|
rt::set_signal_stack(new.ss_sp.addr(), new.ss_size);
|
|
}
|
|
CIntZeroResult::SUCCESS
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigdelset(_mask: *mut sigset_t, _signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigemptyset(mask: *mut sigset_t) -> CIntZeroResult {
|
|
let mask = mask.ensure_mut();
|
|
*mask = 0;
|
|
CIntZeroResult::SUCCESS
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigfillset(_mask: *mut sigset_t) -> c_int {
|
|
0
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sighold(_signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigignore(_signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn siginterrupt(_signum: c_int, _b: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigismember(_mask: *const sigset_t, _signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn signal(signum: c_int, handler: sig_handler_t) -> sig_handler_t {
|
|
// Validate handler
|
|
let address = handler as usize;
|
|
// NULL or SIG_ERR
|
|
if address == 0 || address == 1 {
|
|
log::error!("libc: signal() was passed an invalid handler");
|
|
error::errno = Errno::EINVAL;
|
|
// SIG_ERR
|
|
return core::mem::transmute(1usize);
|
|
}
|
|
|
|
match signal::set(signum, handler) {
|
|
EResult::Ok(handler) => handler,
|
|
EResult::Err(err) => {
|
|
error::errno = err;
|
|
// SIG_ERR
|
|
core::mem::transmute(1usize)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigpause(_signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigpending(_mask: *mut sigset_t) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigprocmask(
|
|
_signum: c_int,
|
|
_new: *const sigset_t,
|
|
_old: *mut sigset_t,
|
|
) -> c_int {
|
|
0
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigqueue(_pid: pid_t, _signum: c_int, _val: sigval) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigrelse(_signum: c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigset(_signum: c_int, _handler: sig_handler_t) -> sig_handler_t {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigsuspend(_mask: *const sigset_t) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigtimedwait(
|
|
_mask: *const sigset_t,
|
|
_info: *mut siginfo_t,
|
|
_time: *const __ygg_timespec_t,
|
|
) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigwait(_mask: *const sigset_t, _signum: *mut c_int) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn sigwaitinfo(_mask: *const sigset_t, _info: *mut siginfo_t) -> c_int {
|
|
todo!()
|
|
}
|