Thanks to visit codestin.com
Credit goes to docs.rs

uapi/process/
mod.rs

1#![allow(non_snake_case)]
2
3use crate::*;
4use std::{convert::TryInto, ffi::CStr, mem};
5
6cfg_if::cfg_if! {
7    if #[cfg(target_os = "linux")] {
8        mod linux;
9        pub use linux::*;
10    }
11}
12
13#[man(fork(2))]
14///
15/// # Safety
16///
17/// `fork` is unsafe in multi-threaded programs.
18///
19/// Consider the following example:
20///
21/// ```rust,ignore
22/// #![feature(thread_id_value)]
23///
24/// use std::sync::atomic::{AtomicI32, AtomicPtr};
25/// use std::sync::atomic::Ordering::SeqCst;
26/// use std::{thread, ptr};
27///
28/// pub fn f() {
29///     static I: AtomicI32 = AtomicI32::new(0);
30///     static D: AtomicPtr<i32> = AtomicPtr::new(ptr::null_mut());
31///
32///     let data = Box::leak(Box::new(0));
33///     let tid = gettid();
34///     match I.load(SeqCst) {
35///         0 => {
36///             I.store(tid, SeqCst);
37///             /*
38///              * Assumption for safety: No call to `f` can have the same `tid` while we're
39///              * in the critical section that spans this comment.
40///              */
41///             D.store(data, SeqCst);
42///         },
43///         n if n == tid => {
44///             /* D has been set to a valid pointer because of the assumption above */
45///             let _v = unsafe { *D.load(SeqCst) };
46///         },
47///         _ => { },
48///     }
49/// }
50/// ```
51///
52/// If `fork` is called while another thread is in the critical section, `I` will be
53/// initialized in the child but `D` won't. If the child creates a new thread, the new
54/// thread might have the same `tid` as the thread in the critical section. Therefore the
55/// child thread will dereference a null pointer.
56///
57/// Consult the upstream documentation.
58pub unsafe fn fork() -> Result<c::pid_t> {
59    let res = c::fork();
60    map_err!(res)
61}
62
63#[man(wait(2))]
64pub fn wait() -> Result<(c::pid_t, c::c_int)> {
65    let mut wstatus = 0;
66    let res = unsafe { c::wait(&mut wstatus) };
67    map_err!(res).map(|pid| (pid, wstatus))
68}
69
70#[man(waitpid(2))]
71pub fn waitpid(pid: c::pid_t, options: c::c_int) -> Result<(c::pid_t, c::c_int)> {
72    let mut wstatus = 0;
73    let res = unsafe { c::waitpid(pid, &mut wstatus, options) };
74    map_err!(res).map(|pid| (pid, wstatus))
75}
76
77#[man(chroot(2))]
78pub fn chroot<'a>(path: impl IntoUstr<'a>) -> Result<()> {
79    let path = path.into_ustr();
80    let res = unsafe { c::chroot(path.as_ptr()) };
81    map_err!(res).map(drop)
82}
83
84#[man(execve(2))]
85pub fn execve<'a>(
86    pathname: impl IntoUstr<'a>,
87    argv: &UstrPtr,
88    envp: &UstrPtr,
89) -> Result<()> {
90    let pathname = pathname.into_ustr();
91    let res = unsafe { c::execve(pathname.as_ptr(), argv.as_ptr(), envp.as_ptr()) };
92    map_err!(res).map(drop)
93}
94
95#[man(execv(3))]
96pub fn execv<'a, 'b>(pathname: impl IntoUstr<'a>, argv: &UstrPtr) -> Result<()> {
97    let pathname = pathname.into_ustr();
98    let res = unsafe { c::execv(pathname.as_ptr(), argv.as_ptr()) };
99    map_err!(res).map(drop)
100}
101
102#[man(execvp(3))]
103pub fn execvp<'a, 'b>(pathname: impl IntoUstr<'a>, argv: &UstrPtr) -> Result<()> {
104    let pathname = pathname.into_ustr();
105    let res = unsafe { c::execvp(pathname.as_ptr(), argv.as_ptr()) };
106    map_err!(res).map(drop)
107}
108
109#[man(fexecve(3))]
110#[cfg(not(any(target_os = "macos", target_os = "openbsd")))]
111pub fn fexecve(fd: c::c_int, argv: &UstrPtr, envp: &UstrPtr) -> Result<()> {
112    let res = unsafe { c::fexecve(fd, argv.as_ptr(), envp.as_ptr()) };
113    map_err!(res).map(drop)
114}
115
116#[man(getcwd(3))]
117pub fn getcwd<T: Pod + ?Sized>(buf: &mut T) -> Result<&CStr> {
118    unsafe {
119        let buf = as_maybe_uninit_bytes_mut2(buf);
120        let res = c::getcwd(buf.as_mut_ptr() as *mut _, buf.len());
121        if res.is_null() {
122            Err(Errno::default())
123        } else {
124            Ok(CStr::from_ptr(res))
125        }
126    }
127}
128
129#[man(setuid(2))]
130pub fn setuid(uid: c::uid_t) -> Result<()> {
131    let res = unsafe { c::setuid(uid) };
132    map_err!(res).map(drop)
133}
134
135#[man(seteuid(2))]
136pub fn seteuid(uid: c::uid_t) -> Result<()> {
137    let res = unsafe { c::seteuid(uid) };
138    map_err!(res).map(drop)
139}
140
141#[man(setgid(2))]
142pub fn setgid(gid: c::gid_t) -> Result<()> {
143    let res = unsafe { c::setgid(gid) };
144    map_err!(res).map(drop)
145}
146
147#[man(setegid(2))]
148pub fn setegid(gid: c::gid_t) -> Result<()> {
149    let res = unsafe { c::setegid(gid) };
150    map_err!(res).map(drop)
151}
152
153#[man(getuid(2))]
154pub fn getuid() -> c::uid_t {
155    unsafe { c::getuid() }
156}
157
158#[man(geteuid(2))]
159pub fn geteuid() -> c::uid_t {
160    unsafe { c::geteuid() }
161}
162
163#[man(getgid(2))]
164pub fn getgid() -> c::gid_t {
165    unsafe { c::getgid() }
166}
167
168#[man(getegid(2))]
169pub fn getegid() -> c::gid_t {
170    unsafe { c::getegid() }
171}
172
173#[man(getgroups(2))]
174pub fn getgroups(grouplist: &mut [c::gid_t]) -> Result<&mut [c::gid_t]> {
175    let len = grouplist.len().try_into().unwrap_or(c::c_int::max_value());
176    let res = unsafe { c::getgroups(len, grouplist.as_mut_ptr()) };
177    map_err!(res)?;
178    Ok(&mut grouplist[..res as usize])
179}
180
181#[man(setgroups(2))]
182pub fn setgroups(grouplist: &[c::gid_t]) -> Result<()> {
183    let res = unsafe {
184        c::setgroups(grouplist.len().try_into().or(einval())?, grouplist.as_ptr())
185    };
186    map_err!(res).map(drop)
187}
188
189#[man(getpgrp(2))]
190pub fn getpgrp() -> c::pid_t {
191    unsafe { c::getpgrp() }
192}
193
194#[man(setpgid(2))]
195pub fn setpgid(pid: c::pid_t, pgid: c::pid_t) -> Result<()> {
196    let res = unsafe { c::setpgid(pid, pgid) };
197    map_err!(res).map(drop)
198}
199
200#[man(getpid(2))]
201pub fn getpid() -> c::pid_t {
202    unsafe { c::getpid() }
203}
204
205#[man(getppid(2))]
206pub fn getppid() -> c::pid_t {
207    unsafe { c::getppid() }
208}
209
210#[man(setsid(2))]
211pub fn setsid() -> Result<c::pid_t> {
212    let res = unsafe { c::setsid() };
213    map_err!(res)
214}
215
216#[man(getsid(2))]
217pub fn getsid(pid: c::pid_t) -> c::pid_t {
218    unsafe { c::getsid(pid) }
219}
220
221#[man(pause(2))]
222pub fn pause() {
223    unsafe {
224        c::pause();
225    }
226}
227
228#[man(setresuid(2))]
229#[cfg(not(target_os = "macos"))]
230pub fn setresuid(ruid: c::uid_t, euid: c::uid_t, suid: c::uid_t) -> Result<()> {
231    let res = unsafe { c::setresuid(ruid, euid, suid) };
232    map_err!(res).map(drop)
233}
234
235#[man(setresgid(2))]
236#[cfg(not(target_os = "macos"))]
237pub fn setresgid(rgid: c::gid_t, egid: c::gid_t, sgid: c::gid_t) -> Result<()> {
238    let res = unsafe { c::setresgid(rgid, egid, sgid) };
239    map_err!(res).map(drop)
240}
241
242#[man(getresuid(2))]
243#[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd")))]
244pub fn getresuid() -> Result<(c::uid_t, c::uid_t, c::uid_t)> {
245    let (mut ruid, mut euid, mut suid) = (0, 0, 0);
246    let res = unsafe { c::getresuid(&mut ruid, &mut euid, &mut suid) };
247    map_err!(res).map(|_| (ruid, euid, suid))
248}
249
250#[man(getresgid(2))]
251#[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd")))]
252pub fn getresgid() -> Result<(c::gid_t, c::gid_t, c::gid_t)> {
253    let (mut rgid, mut egid, mut sgid) = (0, 0, 0);
254    let res = unsafe { c::getresgid(&mut rgid, &mut egid, &mut sgid) };
255    map_err!(res).map(|_| (rgid, egid, sgid))
256}
257
258#[man(clock_getres(2))]
259pub fn clock_getres(clockid: c::clockid_t, tp: &mut c::timespec) -> Result<()> {
260    let res = unsafe { c::clock_getres(clockid, tp) };
261    map_err!(res).map(drop)
262}
263
264#[man(clock_gettime(2))]
265pub fn clock_gettime(clockid: c::clockid_t, tp: &mut c::timespec) -> Result<()> {
266    let res = unsafe { c::clock_gettime(clockid, tp) };
267    map_err!(res).map(drop)
268}
269
270#[man(clock_settime(2))]
271#[cfg(not(target_os = "macos"))]
272pub fn clock_settime(clockid: c::clockid_t, tp: &c::timespec) -> Result<()> {
273    let res = unsafe { c::clock_settime(clockid, tp) };
274    map_err!(res).map(drop)
275}
276
277#[man(clock_nanosleep(2))]
278#[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd")))]
279pub fn clock_nanosleep(
280    clockid: c::clockid_t,
281    flags: c::c_int,
282    tp: &c::timespec,
283    remain: Option<&mut c::timespec>,
284) -> Result<()> {
285    use std::ptr;
286    let res = unsafe {
287        c::clock_nanosleep(
288            clockid,
289            flags,
290            tp,
291            remain.map(|v| v as *mut _).unwrap_or(ptr::null_mut()),
292        )
293    };
294    map_err!(res).map(drop)
295}
296
297#[man(kill(2))]
298pub fn kill(pid: c::pid_t, sig: c::c_int) -> Result<()> {
299    let res = unsafe { c::kill(pid, sig) };
300    map_err!(res).map(drop)
301}
302#[man(wait(2))]
303pub fn WEXITSTATUS(s: c::c_int) -> c::c_int {
304    c::WEXITSTATUS(s)
305}
306
307#[man(wait(2))]
308pub fn WTERMSIG(s: c::c_int) -> c::c_int {
309    c::WTERMSIG(s)
310}
311
312#[man(wait(2))]
313pub fn WSTOPSIG(s: c::c_int) -> c::c_int {
314    c::WSTOPSIG(s)
315}
316
317#[man(wait(2))]
318pub fn WIFEXITED(s: c::c_int) -> bool {
319    c::WIFEXITED(s)
320}
321
322#[man(wait(2))]
323pub fn WIFSTOPPED(s: c::c_int) -> bool {
324    c::WIFSTOPPED(s)
325}
326
327#[man(wait(2))]
328pub fn WIFSIGNALED(s: c::c_int) -> bool {
329    c::WIFSIGNALED(s)
330}
331
332#[man(wait(2))]
333pub fn WIFCONTINUED(s: c::c_int) -> bool {
334    // https://github.com/rust-lang/libc/issues/2001
335    #[allow(unused_unsafe)]
336    unsafe {
337        c::WIFCONTINUED(s)
338    }
339}
340
341#[man(wait(2))]
342pub fn WCOREDUMP(s: c::c_int) -> bool {
343    c::WCOREDUMP(s)
344}
345
346#[man(getrlimit(2))]
347pub fn getrlimit(resource: c::c_int) -> Result<c::rlimit> {
348    unsafe {
349        let mut limit = mem::zeroed();
350        map_err!(c::getrlimit(resource as _, &mut limit))?;
351        Ok(limit)
352    }
353}
354
355#[man(setrlimit(2))]
356pub fn setrlimit(resource: c::c_int, limit: &c::rlimit) -> Result<()> {
357    unsafe { map_err!(c::setrlimit(resource as _, limit)).map(drop) }
358}