1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Unix-specific extensions to primitives in the `std::process` module.
13 #![stable(feature = "rust1", since = "1.0.0")]
18 use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
21 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
23 /// Unix-specific extensions to the `std::process::Command` builder
24 #[stable(feature = "rust1", since = "1.0.0")]
25 pub trait CommandExt {
26 /// Sets the child process's user id. This translates to a
27 /// `setuid` call in the child process. Failure in the `setuid`
28 /// call will cause the spawn to fail.
29 #[stable(feature = "rust1", since = "1.0.0")]
30 fn uid(&mut self, id: u32) -> &mut process::Command;
32 /// Similar to `uid`, but sets the group id of the child process. This has
33 /// the same semantics as the `uid` field.
34 #[stable(feature = "rust1", since = "1.0.0")]
35 fn gid(&mut self, id: u32) -> &mut process::Command;
37 /// Schedules a closure to be run just before the `exec` function is
40 /// The closure is allowed to return an I/O error whose OS error code will
41 /// be communicated back to the parent and returned as an error from when
42 /// the spawn was requested.
44 /// Multiple closures can be registered and they will be called in order of
45 /// their registration. If a closure returns `Err` then no further closures
46 /// will be called and the spawn operation will immediately return with a
51 /// This closure will be run in the context of the child process after a
52 /// `fork`. This primarily means that any modificatons made to memory on
53 /// behalf of this closure will **not** be visible to the parent process.
54 /// This is often a very constrained environment where normal operations
55 /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
56 /// other threads perhaps still running when the `fork` was run).
58 /// When this closure is run, aspects such as the stdio file descriptors and
59 /// working directory have successfully been changed, so output to these
60 /// locations may not appear where intended.
61 #[unstable(feature = "process_exec", issue = "31398")]
62 fn before_exec<F>(&mut self, f: F) -> &mut process::Command
63 where F: FnMut() -> io::Result<()> + Send + Sync + 'static;
65 /// Performs all the required setup by this `Command`, followed by calling
66 /// the `execvp` syscall.
68 /// On success this function will not return, and otherwise it will return
69 /// an error indicating why the exec (or another part of the setup of the
70 /// `Command`) failed.
72 /// This function, unlike `spawn`, will **not** `fork` the process to create
73 /// a new child. Like spawn, however, the default behavior for the stdio
74 /// descriptors will be to inherited from the current process.
78 /// The process may be in a "broken state" if this function returns in
79 /// error. For example the working directory, environment variables, signal
80 /// handling settings, various user/group information, or aspects of stdio
81 /// file descriptors may have changed. If a "transactional spawn" is
82 /// required to gracefully handle errors it is recommended to use the
83 /// cross-platform `spawn` instead.
84 #[stable(feature = "process_exec2", since = "1.9.0")]
85 fn exec(&mut self) -> io::Error;
88 #[stable(feature = "rust1", since = "1.0.0")]
89 impl CommandExt for process::Command {
90 fn uid(&mut self, id: u32) -> &mut process::Command {
91 self.as_inner_mut().uid(id);
95 fn gid(&mut self, id: u32) -> &mut process::Command {
96 self.as_inner_mut().gid(id);
100 fn before_exec<F>(&mut self, f: F) -> &mut process::Command
101 where F: FnMut() -> io::Result<()> + Send + Sync + 'static
103 self.as_inner_mut().before_exec(Box::new(f));
107 fn exec(&mut self) -> io::Error {
108 self.as_inner_mut().exec(sys::process::Stdio::Inherit)
112 /// Unix-specific extensions to `std::process::ExitStatus`
113 #[stable(feature = "rust1", since = "1.0.0")]
114 pub trait ExitStatusExt {
115 /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
117 #[unstable(feature = "exit_status_from", issue = "32713")]
118 fn from_raw(raw: i32) -> Self;
120 /// If the process was terminated by a signal, returns that signal.
121 #[stable(feature = "rust1", since = "1.0.0")]
122 fn signal(&self) -> Option<i32>;
125 #[stable(feature = "rust1", since = "1.0.0")]
126 impl ExitStatusExt for process::ExitStatus {
127 fn from_raw(raw: i32) -> Self {
128 process::ExitStatus::from_inner(From::from(raw))
131 fn signal(&self) -> Option<i32> {
132 self.as_inner().signal()
136 #[stable(feature = "process_extensions", since = "1.2.0")]
137 impl FromRawFd for process::Stdio {
138 unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
139 let fd = sys::fd::FileDesc::new(fd);
140 let io = sys::process::Stdio::Fd(fd);
141 process::Stdio::from_inner(io)
145 #[stable(feature = "process_extensions", since = "1.2.0")]
146 impl AsRawFd for process::ChildStdin {
147 fn as_raw_fd(&self) -> RawFd {
148 self.as_inner().fd().raw()
152 #[stable(feature = "process_extensions", since = "1.2.0")]
153 impl AsRawFd for process::ChildStdout {
154 fn as_raw_fd(&self) -> RawFd {
155 self.as_inner().fd().raw()
159 #[stable(feature = "process_extensions", since = "1.2.0")]
160 impl AsRawFd for process::ChildStderr {
161 fn as_raw_fd(&self) -> RawFd {
162 self.as_inner().fd().raw()
166 #[stable(feature = "process_extensions", since = "1.2.0")]
167 impl IntoRawFd for process::ChildStdin {
168 fn into_raw_fd(self) -> RawFd {
169 self.into_inner().into_fd().into_raw()
173 #[stable(feature = "process_extensions", since = "1.2.0")]
174 impl IntoRawFd for process::ChildStdout {
175 fn into_raw_fd(self) -> RawFd {
176 self.into_inner().into_fd().into_raw()
180 #[stable(feature = "process_extensions", since = "1.2.0")]
181 impl IntoRawFd for process::ChildStderr {
182 fn into_raw_fd(self) -> RawFd {
183 self.into_inner().into_fd().into_raw()