1use core::mem::zeroed;
2use errno::{set_errno, Errno};
3use libc::{c_int, id_t, idtype_t, pid_t, siginfo_t};
4use rustix::fd::BorrowedFd;
5use rustix::process::{Pid, WaitId, WaitIdOptions, WaitOptions};
6
7use crate::convert_res;
8
9#[no_mangle]
10unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
11 libc!(libc::waitpid(pid, status, options));
12 let options = WaitOptions::from_bits(options as _).unwrap();
13 let ret_pid;
14 let ret_status;
15 match pid {
16 -1 => match convert_res(rustix::process::wait(options)) {
17 Some(Some((new_pid, new_status))) => {
18 ret_pid = new_pid.as_raw_nonzero().get() as c_int;
19 ret_status = new_status.as_raw() as c_int;
20 }
21 Some(None) => return 0,
22 None => return -1,
23 },
24 pid if pid == pid_t::MIN => {
25 set_errno(Errno(libc::ESRCH));
26 return -1;
27 }
28 pid if pid < 0 => match convert_res(rustix::process::waitpgid(
29 Pid::from_raw_unchecked(pid.wrapping_neg()),
30 options,
31 )) {
32 Some(Some(new_status)) => {
33 ret_pid = if pid == 0 {
34 rustix::process::getpid().as_raw_nonzero().get() as c_int
35 } else {
36 pid
37 };
38 ret_status = new_status.1.as_raw() as c_int;
39 }
40 Some(None) => return 0,
41 None => return -1,
42 },
43 pid => match convert_res(rustix::process::waitpid(Pid::from_raw(pid as _), options)) {
44 Some(Some(new_status)) => {
45 ret_pid = if pid == 0 {
46 rustix::process::getpid().as_raw_nonzero().get() as c_int
47 } else {
48 pid
49 };
50 ret_status = new_status.1.as_raw() as c_int;
51 }
52 Some(None) => return 0,
53 None => return -1,
54 },
55 }
56 if !status.is_null() {
57 status.write(ret_status);
58 }
59 ret_pid
60}
61
62#[no_mangle]
63unsafe extern "C" fn wait(status: *mut c_int) -> pid_t {
64 libc!(libc::wait(status));
65 waitpid(-1, status, 0)
66}
67
68#[no_mangle]
69unsafe extern "C" fn waitid(
70 idtype: idtype_t,
71 id: id_t,
72 infop: *mut siginfo_t,
73 options: c_int,
74) -> c_int {
75 libc!(libc::waitid(idtype, id, infop, options));
76
77 let id = match idtype {
78 libc::P_PID => {
79 if let Some(pid) = Pid::from_raw(id as _) {
80 WaitId::Pid(pid)
81 } else {
82 set_errno(Errno(libc::EINVAL));
83 return -1;
84 }
85 }
86 libc::P_PIDFD => WaitId::PidFd(BorrowedFd::borrow_raw(id as _)),
87 libc::P_PGID => WaitId::Pgid(Pid::from_raw(id as _)),
88 libc::P_ALL => WaitId::All,
89 _ => {
90 set_errno(Errno(libc::EINVAL));
91 return -1;
92 }
93 };
94
95 let options = WaitIdOptions::from_bits(options as _).unwrap();
96
97 match convert_res(rustix::process::waitid(id, options)) {
98 Some(Some(new_info)) => {
99 *infop = zeroed();
100 (*infop).si_signo = new_info.raw_signo();
101 (*infop).si_errno = new_info.raw_errno();
102 (*infop).si_code = new_info.raw_code();
103 0
104 }
105 Some(None) => 0,
106 None => -1,
107 }
108}