]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/vxworks/process/process_vxworks.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / libstd / sys / vxworks / process / process_vxworks.rs
1 use crate::io::{self, Error, ErrorKind};
2 use libc::{self, c_int, c_char};
3 use libc::{RTP_ID};
4 use crate::sys;
5 use crate::sys::cvt;
6 use crate::sys::process::rtp;
7 use crate::sys::process::process_common::*;
8
9 ////////////////////////////////////////////////////////////////////////////////
10 // Command
11 ////////////////////////////////////////////////////////////////////////////////
12
13 impl Command {
14 pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
15 -> io::Result<(Process, StdioPipes)> {
16 use crate::sys::{cvt_r};
17 const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
18
19 if self.saw_nul() {
20 return Err(io::Error::new(ErrorKind::InvalidInput,
21 "nul byte found in provided data"));
22 }
23 let (ours, theirs) = self.setup_io(default, needs_stdin)?;
24 let mut p = Process { pid: 0, status: None };
25
26 unsafe {
27 macro_rules! t {
28 ($e:expr) => (match $e {
29 Ok(e) => e,
30 Err(e) => return Err(e.into()),
31 })
32 }
33
34 let mut orig_stdin = libc::STDIN_FILENO;
35 let mut orig_stdout = libc::STDOUT_FILENO;
36 let mut orig_stderr = libc::STDERR_FILENO;
37
38 if let Some(fd) = theirs.stdin.fd() {
39 orig_stdin = t!(cvt_r(|| libc::dup(libc::STDIN_FILENO)));
40 t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
41 }
42 if let Some(fd) = theirs.stdout.fd() {
43 orig_stdout = t!(cvt_r(|| libc::dup(libc::STDOUT_FILENO)));
44 t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
45 }
46 if let Some(fd) = theirs.stderr.fd() {
47 orig_stderr = t!(cvt_r(|| libc::dup(libc::STDERR_FILENO)));
48 t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
49 }
50
51 if let Some(ref cwd) = *self.get_cwd() {
52 t!(cvt(libc::chdir(cwd.as_ptr())));
53 }
54
55 let ret = rtp::rtpSpawn(
56 self.get_argv()[0], // executing program
57 self.get_argv().as_ptr() as *const _, // argv
58 *sys::os::environ() as *const *const c_char,
59 100 as c_int, // initial priority
60 0x16000, // initial stack size. 0 defaults
61 // to 0x4000 in 32 bit and 0x8000 in 64 bit
62 0, // options
63 0 // task options
64 );
65
66 // Because FileDesc was not used, each duplicated file descriptor
67 // needs to be closed manually
68 if orig_stdin != libc::STDIN_FILENO {
69 t!(cvt_r(|| libc::dup2(orig_stdin, libc::STDIN_FILENO)));
70 libc::close(orig_stdin);
71 }
72 if orig_stdout != libc::STDOUT_FILENO {
73 t!(cvt_r(|| libc::dup2(orig_stdout, libc::STDOUT_FILENO)));
74 libc::close(orig_stdout);
75 }
76 if orig_stderr != libc::STDERR_FILENO {
77 t!(cvt_r(|| libc::dup2(orig_stderr, libc::STDERR_FILENO)));
78 libc::close(orig_stderr);
79 }
80
81 if ret != rtp::RTP_ID_ERROR {
82 p.pid = ret;
83 Ok((p, ours))
84 } else {
85 Err(io::Error::last_os_error())
86 }
87 }
88 }
89
90 pub fn exec(&mut self, default: Stdio) -> io::Error {
91 let ret = Command::spawn(self, default, false);
92 match ret {
93 Ok(t) => unsafe {
94 let mut status = 0 as c_int;
95 libc::waitpid(t.0.pid, &mut status, 0);
96 libc::exit(0);
97 },
98 Err(e) => e,
99 }
100 }
101 }
102
103 ////////////////////////////////////////////////////////////////////////////////
104 // Processes
105 ////////////////////////////////////////////////////////////////////////////////
106
107 /// The unique id of the process (this should never be negative).
108 pub struct Process {
109 pid: RTP_ID,
110 status: Option<ExitStatus>,
111 }
112
113 impl Process {
114 pub fn id(&self) -> u32 {
115 self.pid as u32
116 }
117
118 pub fn kill(&mut self) -> io::Result<()> {
119 // If we've already waited on this process then the pid can be recycled
120 // and used for another process, and we probably shouldn't be killing
121 // random processes, so just return an error.
122 if self.status.is_some() {
123 Err(Error::new(ErrorKind::InvalidInput,
124 "invalid argument: can't kill an exited process"))
125 } else {
126 cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ())
127 }
128 }
129
130 pub fn wait(&mut self) -> io::Result<ExitStatus> {
131 use crate::sys::cvt_r;
132 if let Some(status) = self.status {
133 return Ok(status)
134 }
135 let mut status = 0 as c_int;
136 cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
137 self.status = Some(ExitStatus::new(status));
138 Ok(ExitStatus::new(status))
139 }
140
141 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
142 if let Some(status) = self.status {
143 return Ok(Some(status))
144 }
145 let mut status = 0 as c_int;
146 let pid = cvt(unsafe {
147 libc::waitpid(self.pid, &mut status, libc::WNOHANG)
148 })?;
149 if pid == 0 {
150 Ok(None)
151 } else {
152 self.status = Some(ExitStatus::new(status));
153 Ok(Some(ExitStatus::new(status)))
154 }
155 }
156 }