1use super::{
2 super::{Pal, PalSignal, types::*},
3 Sys,
4};
5#[allow(deprecated)]
6use crate::header::sys_time::{ITIMER_REAL, itimerval};
7use crate::{
8 error::{Errno, Result},
9 header::{
10 bits_sigset_t::sigset_t,
11 errno::{EINVAL, ENOSYS},
12 signal::{
13 SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK,
14 sigaction, siginfo_t, sigval, stack_t, ucontext_t,
15 },
16 time::timespec,
17 },
18};
19use core::mem::offset_of;
20use redox_protocols::protocol::ProcKillTarget;
21use redox_rt::signal::{
22 PosixStackt, SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler,
23};
24
25const _: () = {
26 #[track_caller]
27 const fn assert_eq(a: usize, b: usize) {
28 if a != b {
29 panic!("compile-time struct verification failed");
30 }
31 }
32 assert_eq(offset_of!(ucontext_t, uc_link), offset_of!(SigStack, link));
33 assert_eq(
34 offset_of!(ucontext_t, uc_stack),
35 offset_of!(SigStack, old_stack),
36 );
37 assert_eq(
38 offset_of!(ucontext_t, uc_sigmask),
39 offset_of!(SigStack, old_mask),
40 );
41 assert_eq(
42 offset_of!(ucontext_t, uc_mcontext),
43 offset_of!(SigStack, regs),
44 );
45};
46
47impl PalSignal for Sys {
48 #[allow(deprecated)]
49 fn getitimer(which: c_int, out: &mut itimerval) -> Result<()> {
50 let path = match which {
51 ITIMER_REAL => "/scheme/itimer/1",
52 _ => return Err(Errno(EINVAL)),
53 };
54 let spec = syscall::ITimerSpec::default();
59 out.it_interval.tv_sec = spec.it_interval.tv_sec as time_t;
60 out.it_interval.tv_usec = spec.it_interval.tv_nsec / 1000;
61 out.it_value.tv_sec = spec.it_value.tv_sec as time_t;
62 out.it_value.tv_usec = spec.it_value.tv_nsec / 1000;
63
64 Ok(())
65 }
66
67 fn kill(pid: pid_t, sig: c_int) -> Result<()> {
68 redox_rt::sys::posix_kill(ProcKillTarget::from_raw(pid as usize), sig as usize)?;
69 Ok(())
70 }
71 fn sigqueue(pid: pid_t, sig: c_int, val: sigval) -> Result<()> {
72 Ok(redox_rt::sys::posix_sigqueue(
73 pid as usize,
74 sig as usize,
75 unsafe { val.sival_ptr } as usize,
76 )?)
77 }
78
79 fn killpg(pgrp: pid_t, sig: c_int) -> Result<()> {
80 if pgrp == 1 {
81 return Err(Errno(EINVAL));
82 }
83 Self::kill(-pgrp, sig)
84 }
85
86 fn raise(sig: c_int) -> Result<()> {
87 unsafe { Self::rlct_kill(Self::current_os_tid(), sig as _) }
89 }
90
91 #[allow(deprecated)]
92 fn setitimer(which: c_int, _new: &itimerval, old: Option<&mut itimerval>) -> Result<()> {
93 todo_skip!(0, "setitimer not implemented");
97 Err(Errno(ENOSYS))
98 }
99
100 fn sigaction(
101 sig: c_int,
102 c_act: Option<&sigaction>,
103 c_oact: Option<&mut sigaction>,
104 ) -> Result<(), Errno> {
105 let sig = u8::try_from(sig).map_err(|_| syscall::Error::new(syscall::EINVAL))?;
106
107 let new_action = c_act.map(|c_act| {
108 let handler = c_act.sa_handler.map_or(0, |f| f as usize);
109
110 let kind = if handler == SIG_DFL {
111 SigactionKind::Default
112 } else if handler == SIG_IGN {
113 SigactionKind::Ignore
114 } else {
115 SigactionKind::Handled {
116 handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as c_int != 0 {
117 SignalHandler {
118 sigaction: unsafe { core::mem::transmute(c_act.sa_handler) },
119 }
120 } else {
121 SignalHandler {
122 handler: c_act.sa_handler,
123 }
124 },
125 }
126 };
127
128 Sigaction {
129 kind,
130 mask: c_act.sa_mask,
131 flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
132 }
133 });
134 let mut old_action = c_oact.as_ref().map(|_| Sigaction::default());
135
136 redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
137
138 if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
139 *c_oact = match old_action.kind {
140 SigactionKind::Ignore => sigaction {
141 sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
142 sa_flags: 0,
143 sa_restorer: None,
144 sa_mask: 0,
145 },
146 SigactionKind::Default => sigaction {
147 sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
148 sa_flags: 0,
149 sa_restorer: None,
150 sa_mask: 0,
151 },
152 SigactionKind::Handled { handler } => sigaction {
153 sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
154 unsafe { core::mem::transmute(handler.sigaction) }
155 } else {
156 unsafe { handler.handler }
157 },
158 sa_restorer: None,
159 sa_flags: old_action.flags.bits() as c_int,
160 sa_mask: old_action.mask,
161 },
162 };
163 }
164 Ok(())
165 }
166
167 unsafe fn sigaltstack(
168 new_c: Option<&stack_t>,
169 old_c: Option<&mut stack_t>,
170 ) -> Result<(), Errno> {
171 let new = new_c
172 .map(|c_stack| {
173 let flags = usize::try_from(c_stack.ss_flags).map_err(|_| Errno(EINVAL))?;
174 if flags != flags & (SS_DISABLE | SS_ONSTACK) {
175 return Err(Errno(EINVAL));
176 }
177
178 Ok(if flags & SS_DISABLE == SS_DISABLE {
179 Sigaltstack::Disabled
180 } else {
181 Sigaltstack::Enabled {
182 onstack: false,
183 base: c_stack.ss_sp.cast(),
184 size: c_stack.ss_size,
185 }
186 })
187 })
188 .transpose()?;
189
190 let mut old = old_c.as_ref().map(|_| Sigaltstack::default());
191 (unsafe { redox_rt::signal::sigaltstack(new.as_ref(), old.as_mut()) })?;
192
193 if let (Some(old_c_stack), Some(old)) = (old_c, old) {
194 let c_stack = PosixStackt::from(old);
195 *old_c_stack = stack_t {
196 ss_sp: c_stack.sp.cast(),
197 ss_size: c_stack.size,
198 ss_flags: c_stack.flags,
199 };
200 }
201 Ok(())
202 }
203
204 fn sigpending(set: &mut sigset_t) -> Result<(), Errno> {
205 *set = redox_rt::signal::currently_pending_blocked();
206 Ok(())
207 }
208
209 fn sigprocmask(
210 how: c_int,
211 set: Option<&sigset_t>,
212 oset: Option<&mut sigset_t>,
213 ) -> Result<(), Errno> {
214 match how {
215 _ if set.is_none() => {
216 if let Some(oset) = oset {
217 *oset = redox_rt::signal::get_sigmask()?;
218 }
219 }
220 SIG_SETMASK => redox_rt::signal::set_sigmask(set.copied(), oset)?,
221 SIG_BLOCK => redox_rt::signal::or_sigmask(set.copied(), oset)?,
222 SIG_UNBLOCK => redox_rt::signal::andn_sigmask(set.copied(), oset)?,
223
224 _ => return Err(Errno(EINVAL)),
225 }
226 Ok(())
227 }
228
229 fn sigsuspend(mask: &sigset_t) -> Errno {
230 match redox_rt::signal::await_signal_async(!*mask) {
231 Ok(_) => unreachable!(),
232 Err(err) => err.into(),
233 }
234 }
235
236 fn sigtimedwait(
237 set: &sigset_t,
238 info_out: Option<&mut siginfo_t>,
239 timeout: Option<×pec>,
240 ) -> Result<c_int, Errno> {
241 let timeout = timeout.map(|timeout| syscall::TimeSpec {
243 tv_sec: timeout.tv_sec,
244 tv_nsec: timeout.tv_nsec as _,
245 });
246 let info = redox_rt::signal::await_signal_sync(*set, timeout.as_ref())?.into();
247 if let Some(out) = info_out {
248 *out = info;
249 }
250 Ok(info.si_signo)
251 }
252}