]> git.proxmox.com Git - rustc.git/blob - library/std/src/sys/vxworks/process/process_vxworks.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / library / std / src / sys / vxworks / process / process_vxworks.rs
1 use crate::fmt;
2 use crate::io::{self, Error, ErrorKind};
3 use crate::sys;
4 use crate::sys::cvt;
5 use crate::sys::process::process_common::*;
6 use crate::sys_common::thread;
7 use libc::RTP_ID;
8 use libc::{self, c_char, c_int};
9
10 ////////////////////////////////////////////////////////////////////////////////
11 // Command
12 ////////////////////////////////////////////////////////////////////////////////
13
14 impl Command {
15 pub fn spawn(
16 &mut self,
17 default: Stdio,
18 needs_stdin: bool,
19 ) -> io::Result<(Process, StdioPipes)> {
20 use crate::sys::cvt_r;
21 const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
22 let envp = self.capture_env();
23
24 if self.saw_nul() {
25 return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"));
26 }
27 let (ours, theirs) = self.setup_io(default, needs_stdin)?;
28 let mut p = Process { pid: 0, status: None };
29
30 unsafe {
31 macro_rules! t {
32 ($e:expr) => {
33 match $e {
34 Ok(e) => e,
35 Err(e) => return Err(e.into()),
36 }
37 };
38 }
39
40 let mut orig_stdin = libc::STDIN_FILENO;
41 let mut orig_stdout = libc::STDOUT_FILENO;
42 let mut orig_stderr = libc::STDERR_FILENO;
43
44 if let Some(fd) = theirs.stdin.fd() {
45 orig_stdin = t!(cvt_r(|| libc::dup(libc::STDIN_FILENO)));
46 t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
47 }
48 if let Some(fd) = theirs.stdout.fd() {
49 orig_stdout = t!(cvt_r(|| libc::dup(libc::STDOUT_FILENO)));
50 t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
51 }
52 if let Some(fd) = theirs.stderr.fd() {
53 orig_stderr = t!(cvt_r(|| libc::dup(libc::STDERR_FILENO)));
54 t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
55 }
56
57 if let Some(ref cwd) = *self.get_cwd() {
58 t!(cvt(libc::chdir(cwd.as_ptr())));
59 }
60
61 let c_envp = envp
62 .as_ref()
63 .map(|c| c.as_ptr())
64 .unwrap_or_else(|| *sys::os::environ() as *const _);
65 let stack_size = thread::min_stack();
66
67 // ensure that access to the environment is synchronized
68 let _lock = sys::os::env_lock();
69
70 let ret = libc::rtpSpawn(
71 self.get_program_cstr().as_ptr(),
72 self.get_argv().as_ptr() as *mut *const c_char, // argv
73 c_envp as *mut *const c_char,
74 100 as c_int, // initial priority
75 stack_size, // initial stack size.
76 0, // options
77 0, // task options
78 );
79
80 // Because FileDesc was not used, each duplicated file descriptor
81 // needs to be closed manually
82 if orig_stdin != libc::STDIN_FILENO {
83 t!(cvt_r(|| libc::dup2(orig_stdin, libc::STDIN_FILENO)));
84 libc::close(orig_stdin);
85 }
86 if orig_stdout != libc::STDOUT_FILENO {
87 t!(cvt_r(|| libc::dup2(orig_stdout, libc::STDOUT_FILENO)));
88 libc::close(orig_stdout);
89 }
90 if orig_stderr != libc::STDERR_FILENO {
91 t!(cvt_r(|| libc::dup2(orig_stderr, libc::STDERR_FILENO)));
92 libc::close(orig_stderr);
93 }
94
95 if ret != libc::RTP_ID_ERROR {
96 p.pid = ret;
97 Ok((p, ours))
98 } else {
99 Err(io::Error::last_os_error())
100 }
101 }
102 }
103
104 pub fn exec(&mut self, default: Stdio) -> io::Error {
105 let ret = Command::spawn(self, default, false);
106 match ret {
107 Ok(t) => unsafe {
108 let mut status = 0 as c_int;
109 libc::waitpid(t.0.pid, &mut status, 0);
110 libc::exit(0);
111 },
112 Err(e) => e,
113 }
114 }
115 }
116
117 ////////////////////////////////////////////////////////////////////////////////
118 // Processes
119 ////////////////////////////////////////////////////////////////////////////////
120
121 /// The unique id of the process (this should never be negative).
122 pub struct Process {
123 pid: RTP_ID,
124 status: Option<ExitStatus>,
125 }
126
127 impl Process {
128 pub fn id(&self) -> u32 {
129 self.pid as u32
130 }
131
132 pub fn kill(&mut self) -> io::Result<()> {
133 // If we've already waited on this process then the pid can be recycled
134 // and used for another process, and we probably shouldn't be killing
135 // random processes, so just return an error.
136 if self.status.is_some() {
137 Err(Error::new(
138 ErrorKind::InvalidInput,
139 "invalid argument: can't kill an exited process",
140 ))
141 } else {
142 cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
143 }
144 }
145
146 pub fn wait(&mut self) -> io::Result<ExitStatus> {
147 use crate::sys::cvt_r;
148 if let Some(status) = self.status {
149 return Ok(status);
150 }
151 let mut status = 0 as c_int;
152 cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
153 self.status = Some(ExitStatus::new(status));
154 Ok(ExitStatus::new(status))
155 }
156
157 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
158 if let Some(status) = self.status {
159 return Ok(Some(status));
160 }
161 let mut status = 0 as c_int;
162 let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?;
163 if pid == 0 {
164 Ok(None)
165 } else {
166 self.status = Some(ExitStatus::new(status));
167 Ok(Some(ExitStatus::new(status)))
168 }
169 }
170 }
171
172 /// Unix exit statuses
173 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
174 pub struct ExitStatus(c_int);
175
176 impl ExitStatus {
177 pub fn new(status: c_int) -> ExitStatus {
178 ExitStatus(status)
179 }
180
181 fn exited(&self) -> bool {
182 libc::WIFEXITED(self.0)
183 }
184
185 pub fn success(&self) -> bool {
186 self.code() == Some(0)
187 }
188
189 pub fn code(&self) -> Option<i32> {
190 if self.exited() { Some(libc::WEXITSTATUS(self.0)) } else { None }
191 }
192
193 pub fn signal(&self) -> Option<i32> {
194 if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
195 }
196 }
197
198 /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
199 impl From<c_int> for ExitStatus {
200 fn from(a: c_int) -> ExitStatus {
201 ExitStatus(a)
202 }
203 }
204
205 impl fmt::Display for ExitStatus {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 if let Some(code) = self.code() {
208 write!(f, "exit code: {}", code)
209 } else {
210 let signal = self.signal().unwrap();
211 write!(f, "signal: {}", signal)
212 }
213 }
214 }