]> git.proxmox.com Git - rustc.git/blame - library/std/src/sys/unix/process/process_vxworks.rs
New upstream version 1.72.1+dfsg1
[rustc.git] / library / std / src / sys / unix / process / process_vxworks.rs
CommitLineData
29967ef6 1use crate::fmt;
416331ca 2use crate::io::{self, Error, ErrorKind};
17df50a5 3use crate::num::NonZeroI32;
416331ca
XL
4use crate::sys;
5use crate::sys::cvt;
416331ca 6use crate::sys::process::process_common::*;
e1599b0c 7use crate::sys_common::thread;
5e7ed085 8use core::ffi::NonZero_c_int;
dfeec247
XL
9use libc::RTP_ID;
10use libc::{self, c_char, c_int};
416331ca
XL
11
12////////////////////////////////////////////////////////////////////////////////
13// Command
14////////////////////////////////////////////////////////////////////////////////
15
16impl Command {
dfeec247
XL
17 pub fn spawn(
18 &mut self,
19 default: Stdio,
20 needs_stdin: bool,
21 ) -> io::Result<(Process, StdioPipes)> {
22 use crate::sys::cvt_r;
60c5eb7d 23 let envp = self.capture_env();
416331ca
XL
24
25 if self.saw_nul() {
5099ac24 26 return Err(io::const_io_error!(
cdc7bbd5 27 ErrorKind::InvalidInput,
5099ac24 28 "nul byte found in provided data",
cdc7bbd5 29 ));
416331ca
XL
30 }
31 let (ours, theirs) = self.setup_io(default, needs_stdin)?;
32 let mut p = Process { pid: 0, status: None };
33
34 unsafe {
35 macro_rules! t {
dfeec247
XL
36 ($e:expr) => {
37 match $e {
38 Ok(e) => e,
39 Err(e) => return Err(e.into()),
40 }
41 };
416331ca
XL
42 }
43
44 let mut orig_stdin = libc::STDIN_FILENO;
45 let mut orig_stdout = libc::STDOUT_FILENO;
46 let mut orig_stderr = libc::STDERR_FILENO;
47
48 if let Some(fd) = theirs.stdin.fd() {
49 orig_stdin = t!(cvt_r(|| libc::dup(libc::STDIN_FILENO)));
50 t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
51 }
52 if let Some(fd) = theirs.stdout.fd() {
53 orig_stdout = t!(cvt_r(|| libc::dup(libc::STDOUT_FILENO)));
54 t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
55 }
56 if let Some(fd) = theirs.stderr.fd() {
57 orig_stderr = t!(cvt_r(|| libc::dup(libc::STDERR_FILENO)));
58 t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
59 }
60
61 if let Some(ref cwd) = *self.get_cwd() {
62 t!(cvt(libc::chdir(cwd.as_ptr())));
63 }
64
cdc7bbd5
XL
65 // pre_exec closures are ignored on VxWorks
66 let _ = self.get_closures();
67
dfeec247
XL
68 let c_envp = envp
69 .as_ref()
70 .map(|c| c.as_ptr())
60c5eb7d
XL
71 .unwrap_or_else(|| *sys::os::environ() as *const _);
72 let stack_size = thread::min_stack();
73
74 // ensure that access to the environment is synchronized
cdc7bbd5 75 let _lock = sys::os::env_read_lock();
60c5eb7d 76
e1599b0c 77 let ret = libc::rtpSpawn(
29967ef6 78 self.get_program_cstr().as_ptr(),
e1599b0c 79 self.get_argv().as_ptr() as *mut *const c_char, // argv
60c5eb7d 80 c_envp as *mut *const c_char,
dfeec247
XL
81 100 as c_int, // initial priority
82 stack_size, // initial stack size.
83 0, // options
84 0, // task options
416331ca
XL
85 );
86
87 // Because FileDesc was not used, each duplicated file descriptor
88 // needs to be closed manually
89 if orig_stdin != libc::STDIN_FILENO {
90 t!(cvt_r(|| libc::dup2(orig_stdin, libc::STDIN_FILENO)));
91 libc::close(orig_stdin);
92 }
93 if orig_stdout != libc::STDOUT_FILENO {
94 t!(cvt_r(|| libc::dup2(orig_stdout, libc::STDOUT_FILENO)));
95 libc::close(orig_stdout);
96 }
97 if orig_stderr != libc::STDERR_FILENO {
98 t!(cvt_r(|| libc::dup2(orig_stderr, libc::STDERR_FILENO)));
99 libc::close(orig_stderr);
100 }
101
e1599b0c 102 if ret != libc::RTP_ID_ERROR {
416331ca
XL
103 p.pid = ret;
104 Ok((p, ours))
105 } else {
106 Err(io::Error::last_os_error())
107 }
108 }
109 }
110
9c376795
FG
111 pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
112 let (proc, pipes) = self.spawn(Stdio::MakePipe, false)?;
113 crate::sys_common::process::wait_with_output(proc, pipes)
114 }
115
416331ca
XL
116 pub fn exec(&mut self, default: Stdio) -> io::Error {
117 let ret = Command::spawn(self, default, false);
118 match ret {
119 Ok(t) => unsafe {
120 let mut status = 0 as c_int;
121 libc::waitpid(t.0.pid, &mut status, 0);
122 libc::exit(0);
123 },
124 Err(e) => e,
125 }
126 }
127}
128
129////////////////////////////////////////////////////////////////////////////////
130// Processes
131////////////////////////////////////////////////////////////////////////////////
132
133/// The unique id of the process (this should never be negative).
134pub struct Process {
135 pid: RTP_ID,
136 status: Option<ExitStatus>,
137}
138
139impl Process {
140 pub fn id(&self) -> u32 {
141 self.pid as u32
142 }
143
144 pub fn kill(&mut self) -> io::Result<()> {
145 // If we've already waited on this process then the pid can be recycled
146 // and used for another process, and we probably shouldn't be killing
fe692bf9 147 // random processes, so return Ok because the process has exited already.
416331ca 148 if self.status.is_some() {
fe692bf9 149 Ok(())
416331ca 150 } else {
dfeec247 151 cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
416331ca
XL
152 }
153 }
154
155 pub fn wait(&mut self) -> io::Result<ExitStatus> {
156 use crate::sys::cvt_r;
157 if let Some(status) = self.status {
dfeec247 158 return Ok(status);
416331ca
XL
159 }
160 let mut status = 0 as c_int;
161 cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
162 self.status = Some(ExitStatus::new(status));
163 Ok(ExitStatus::new(status))
164 }
165
166 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
167 if let Some(status) = self.status {
dfeec247 168 return Ok(Some(status));
416331ca
XL
169 }
170 let mut status = 0 as c_int;
dfeec247 171 let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
416331ca
XL
172 if pid == 0 {
173 Ok(None)
174 } else {
175 self.status = Some(ExitStatus::new(status));
176 Ok(Some(ExitStatus::new(status)))
177 }
178 }
179}
29967ef6
XL
180
181/// Unix exit statuses
182#[derive(PartialEq, Eq, Clone, Copy, Debug)]
183pub struct ExitStatus(c_int);
184
185impl ExitStatus {
186 pub fn new(status: c_int) -> ExitStatus {
187 ExitStatus(status)
188 }
189
190 fn exited(&self) -> bool {
191 libc::WIFEXITED(self.0)
192 }
193
17df50a5 194 pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
9c376795 195 // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is
17df50a5 196 // true on all actual versions of Unix, is widely assumed, and is specified in SuS
9c376795 197 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
17df50a5 198 // true for a platform pretending to be Unix, the tests (our doctests, and also
49aad941 199 // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
17df50a5
XL
200 match NonZero_c_int::try_from(self.0) {
201 Ok(failure) => Err(ExitStatusError(failure)),
202 Err(_) => Ok(()),
203 }
29967ef6
XL
204 }
205
206 pub fn code(&self) -> Option<i32> {
207 if self.exited() { Some(libc::WEXITSTATUS(self.0)) } else { None }
208 }
209
210 pub fn signal(&self) -> Option<i32> {
211 if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
212 }
cdc7bbd5
XL
213
214 pub fn core_dumped(&self) -> bool {
215 // This method is not yet properly implemented on VxWorks
216 false
217 }
218
219 pub fn stopped_signal(&self) -> Option<i32> {
220 if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
221 }
222
223 pub fn continued(&self) -> bool {
224 // This method is not yet properly implemented on VxWorks
225 false
226 }
227
228 pub fn into_raw(&self) -> c_int {
229 self.0
230 }
29967ef6
XL
231}
232
233/// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
234impl From<c_int> for ExitStatus {
235 fn from(a: c_int) -> ExitStatus {
236 ExitStatus(a)
237 }
238}
239
240impl fmt::Display for ExitStatus {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 if let Some(code) = self.code() {
5e7ed085 243 write!(f, "exit code: {code}")
29967ef6
XL
244 } else {
245 let signal = self.signal().unwrap();
5e7ed085 246 write!(f, "signal: {signal}")
29967ef6
XL
247 }
248 }
249}
17df50a5
XL
250
251#[derive(PartialEq, Eq, Clone, Copy, Debug)]
252pub struct ExitStatusError(NonZero_c_int);
253
254impl Into<ExitStatus> for ExitStatusError {
255 fn into(self) -> ExitStatus {
256 ExitStatus(self.0.into())
257 }
258}
259
260impl ExitStatusError {
261 pub fn code(self) -> Option<NonZeroI32> {
262 ExitStatus(self.0.into()).code().map(|st| st.try_into().unwrap())
263 }
264}