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