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!()
}