]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | //! Unix-specific extensions to primitives in the `std::process` module. |
476ff2be SL |
2 | |
3 | #![stable(feature = "rust1", since = "1.0.0")] | |
4 | ||
532ac7d7 | 5 | use crate::io; |
532ac7d7 XL |
6 | use crate::process; |
7 | use crate::sys; | |
60c5eb7d XL |
8 | use crate::sys::vxworks::ext::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; |
9 | use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; | |
476ff2be | 10 | |
416331ca | 11 | /// Unix-specific extensions to the [`process::Command`] builder. |
83c7162d XL |
12 | /// |
13 | /// [`process::Command`]: ../../../../std/process/struct.Command.html | |
476ff2be SL |
14 | #[stable(feature = "rust1", since = "1.0.0")] |
15 | pub trait CommandExt { | |
9fa01778 | 16 | /// Sets the child process's user ID. This translates to a |
476ff2be SL |
17 | /// `setuid` call in the child process. Failure in the `setuid` |
18 | /// call will cause the spawn to fail. | |
19 | #[stable(feature = "rust1", since = "1.0.0")] | |
416331ca | 20 | fn uid(&mut self, id: u16) -> &mut process::Command; |
476ff2be | 21 | |
9fa01778 | 22 | /// Similar to `uid`, but sets the group ID of the child process. This has |
476ff2be SL |
23 | /// the same semantics as the `uid` field. |
24 | #[stable(feature = "rust1", since = "1.0.0")] | |
416331ca | 25 | fn gid(&mut self, id: u16) -> &mut process::Command; |
476ff2be SL |
26 | |
27 | /// Schedules a closure to be run just before the `exec` function is | |
28 | /// invoked. | |
29 | /// | |
30 | /// The closure is allowed to return an I/O error whose OS error code will | |
31 | /// be communicated back to the parent and returned as an error from when | |
32 | /// the spawn was requested. | |
33 | /// | |
34 | /// Multiple closures can be registered and they will be called in order of | |
35 | /// their registration. If a closure returns `Err` then no further closures | |
36 | /// will be called and the spawn operation will immediately return with a | |
37 | /// failure. | |
38 | /// | |
9fa01778 | 39 | /// # Notes and Safety |
476ff2be SL |
40 | /// |
41 | /// This closure will be run in the context of the child process after a | |
3b2f2976 | 42 | /// `fork`. This primarily means that any modifications made to memory on |
476ff2be SL |
43 | /// behalf of this closure will **not** be visible to the parent process. |
44 | /// This is often a very constrained environment where normal operations | |
45 | /// like `malloc` or acquiring a mutex are not guaranteed to work (due to | |
46 | /// other threads perhaps still running when the `fork` was run). | |
47 | /// | |
9fa01778 XL |
48 | /// This also means that all resources such as file descriptors and |
49 | /// memory-mapped regions got duplicated. It is your responsibility to make | |
50 | /// sure that the closure does not violate library invariants by making | |
51 | /// invalid use of these duplicates. | |
52 | /// | |
476ff2be SL |
53 | /// When this closure is run, aspects such as the stdio file descriptors and |
54 | /// working directory have successfully been changed, so output to these | |
55 | /// locations may not appear where intended. | |
9fa01778 XL |
56 | #[stable(feature = "process_pre_exec", since = "1.34.0")] |
57 | unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command | |
60c5eb7d XL |
58 | where |
59 | F: FnMut() -> io::Result<()> + Send + Sync + 'static; | |
9fa01778 XL |
60 | |
61 | /// Schedules a closure to be run just before the `exec` function is | |
62 | /// invoked. | |
63 | /// | |
64 | /// This method is stable and usable, but it should be unsafe. To fix | |
65 | /// that, it got deprecated in favor of the unsafe [`pre_exec`]. | |
66 | /// | |
67 | /// [`pre_exec`]: #tymethod.pre_exec | |
476ff2be | 68 | #[stable(feature = "process_exec", since = "1.15.0")] |
9fa01778 | 69 | #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")] |
476ff2be | 70 | fn before_exec<F>(&mut self, f: F) -> &mut process::Command |
60c5eb7d XL |
71 | where |
72 | F: FnMut() -> io::Result<()> + Send + Sync + 'static, | |
9fa01778 XL |
73 | { |
74 | unsafe { self.pre_exec(f) } | |
75 | } | |
476ff2be SL |
76 | |
77 | /// Performs all the required setup by this `Command`, followed by calling | |
78 | /// the `execvp` syscall. | |
79 | /// | |
80 | /// On success this function will not return, and otherwise it will return | |
81 | /// an error indicating why the exec (or another part of the setup of the | |
82 | /// `Command`) failed. | |
83 | /// | |
416331ca XL |
84 | /// `exec` not returning has the same implications as calling |
85 | /// [`process::exit`] – no destructors on the current stack or any other | |
86 | /// thread’s stack will be run. Therefore, it is recommended to only call | |
87 | /// `exec` at a point where it is fine to not run any destructors. Note, | |
88 | /// that the `execvp` syscall independently guarantees that all memory is | |
89 | /// freed and all file descriptors with the `CLOEXEC` option (set by default | |
90 | /// on all file descriptors opened by the standard library) are closed. | |
91 | /// | |
476ff2be SL |
92 | /// This function, unlike `spawn`, will **not** `fork` the process to create |
93 | /// a new child. Like spawn, however, the default behavior for the stdio | |
94 | /// descriptors will be to inherited from the current process. | |
95 | /// | |
416331ca XL |
96 | /// [`process::exit`]: ../../../process/fn.exit.html |
97 | /// | |
476ff2be SL |
98 | /// # Notes |
99 | /// | |
100 | /// The process may be in a "broken state" if this function returns in | |
101 | /// error. For example the working directory, environment variables, signal | |
102 | /// handling settings, various user/group information, or aspects of stdio | |
103 | /// file descriptors may have changed. If a "transactional spawn" is | |
104 | /// required to gracefully handle errors it is recommended to use the | |
105 | /// cross-platform `spawn` instead. | |
106 | #[stable(feature = "process_exec2", since = "1.9.0")] | |
107 | fn exec(&mut self) -> io::Error; | |
108 | } | |
109 | ||
110 | #[stable(feature = "rust1", since = "1.0.0")] | |
111 | impl CommandExt for process::Command { | |
416331ca | 112 | fn uid(&mut self, id: u16) -> &mut process::Command { |
476ff2be SL |
113 | self.as_inner_mut().uid(id); |
114 | self | |
115 | } | |
116 | ||
416331ca | 117 | fn gid(&mut self, id: u16) -> &mut process::Command { |
476ff2be SL |
118 | self.as_inner_mut().gid(id); |
119 | self | |
120 | } | |
121 | ||
9fa01778 | 122 | unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command |
60c5eb7d XL |
123 | where |
124 | F: FnMut() -> io::Result<()> + Send + Sync + 'static, | |
476ff2be | 125 | { |
9fa01778 | 126 | self.as_inner_mut().pre_exec(Box::new(f)); |
476ff2be SL |
127 | self |
128 | } | |
129 | ||
130 | fn exec(&mut self) -> io::Error { | |
131 | self.as_inner_mut().exec(sys::process::Stdio::Inherit) | |
132 | } | |
133 | } | |
134 | ||
416331ca | 135 | /// Unix-specific extensions to [`process::ExitStatus`]. |
83c7162d XL |
136 | /// |
137 | /// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html | |
476ff2be SL |
138 | #[stable(feature = "rust1", since = "1.0.0")] |
139 | pub trait ExitStatusExt { | |
140 | /// Creates a new `ExitStatus` from the raw underlying `i32` return value of | |
141 | /// a process. | |
142 | #[stable(feature = "exit_status_from", since = "1.12.0")] | |
143 | fn from_raw(raw: i32) -> Self; | |
144 | ||
145 | /// If the process was terminated by a signal, returns that signal. | |
146 | #[stable(feature = "rust1", since = "1.0.0")] | |
147 | fn signal(&self) -> Option<i32>; | |
148 | } | |
149 | ||
150 | #[stable(feature = "rust1", since = "1.0.0")] | |
151 | impl ExitStatusExt for process::ExitStatus { | |
152 | fn from_raw(raw: i32) -> Self { | |
153 | process::ExitStatus::from_inner(From::from(raw)) | |
154 | } | |
155 | ||
156 | fn signal(&self) -> Option<i32> { | |
157 | self.as_inner().signal() | |
158 | } | |
159 | } | |
160 | ||
161 | #[stable(feature = "process_extensions", since = "1.2.0")] | |
162 | impl FromRawFd for process::Stdio { | |
163 | unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio { | |
164 | let fd = sys::fd::FileDesc::new(fd); | |
165 | let io = sys::process::Stdio::Fd(fd); | |
166 | process::Stdio::from_inner(io) | |
167 | } | |
168 | } | |
169 | ||
170 | #[stable(feature = "process_extensions", since = "1.2.0")] | |
171 | impl AsRawFd for process::ChildStdin { | |
172 | fn as_raw_fd(&self) -> RawFd { | |
173 | self.as_inner().fd().raw() | |
174 | } | |
175 | } | |
176 | ||
177 | #[stable(feature = "process_extensions", since = "1.2.0")] | |
178 | impl AsRawFd for process::ChildStdout { | |
179 | fn as_raw_fd(&self) -> RawFd { | |
180 | self.as_inner().fd().raw() | |
181 | } | |
182 | } | |
183 | ||
184 | #[stable(feature = "process_extensions", since = "1.2.0")] | |
185 | impl AsRawFd for process::ChildStderr { | |
186 | fn as_raw_fd(&self) -> RawFd { | |
187 | self.as_inner().fd().raw() | |
188 | } | |
189 | } | |
190 | ||
191 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
192 | impl IntoRawFd for process::ChildStdin { | |
193 | fn into_raw_fd(self) -> RawFd { | |
194 | self.into_inner().into_fd().into_raw() | |
195 | } | |
196 | } | |
197 | ||
198 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
199 | impl IntoRawFd for process::ChildStdout { | |
200 | fn into_raw_fd(self) -> RawFd { | |
201 | self.into_inner().into_fd().into_raw() | |
202 | } | |
203 | } | |
204 | ||
205 | #[stable(feature = "into_raw_os", since = "1.4.0")] | |
206 | impl IntoRawFd for process::ChildStderr { | |
207 | fn into_raw_fd(self) -> RawFd { | |
208 | self.into_inner().into_fd().into_raw() | |
209 | } | |
210 | } | |
416331ca XL |
211 | |
212 | /// Returns the OS-assigned process identifier associated with this process's parent. | |
213 | #[stable(feature = "unix_ppid", since = "1.27.0")] | |
214 | pub fn parent_id() -> u32 { | |
215 | crate::sys::os::getppid() | |
216 | } |