| 1 | //! Unix-specific extensions. |
| 2 | |
| 3 | use std::ffi::OsStr; |
| 4 | use std::io; |
| 5 | use std::os::unix::process::CommandExt as _; |
| 6 | |
| 7 | use crate::Command; |
| 8 | |
| 9 | /// Unix-specific extensions to the [`Command`] builder. |
| 10 | /// |
| 11 | /// This trait is sealed: it cannot be implemented outside `async-process`. |
| 12 | /// This is so that future additional methods are not breaking changes. |
| 13 | pub trait CommandExt: crate::sealed::Sealed { |
| 14 | /// Sets the child process's user ID. This translates to a |
| 15 | /// `setuid` call in the child process. Failure in the `setuid` |
| 16 | /// call will cause the spawn to fail. |
| 17 | fn uid(&mut self, id: u32) -> &mut Command; |
| 18 | |
| 19 | /// Similar to `uid`, but sets the group ID of the child process. This has |
| 20 | /// the same semantics as the `uid` field. |
| 21 | fn gid(&mut self, id: u32) -> &mut Command; |
| 22 | |
| 23 | /// Performs all the required setup by this `Command`, followed by calling |
| 24 | /// the `execvp` syscall. |
| 25 | /// |
| 26 | /// On success this function will not return, and otherwise it will return |
| 27 | /// an error indicating why the exec (or another part of the setup of the |
| 28 | /// `Command`) failed. |
| 29 | /// |
| 30 | /// `exec` not returning has the same implications as calling |
| 31 | /// [`std::process::exit`] – no destructors on the current stack or any other |
| 32 | /// thread’s stack will be run. Therefore, it is recommended to only call |
| 33 | /// `exec` at a point where it is fine to not run any destructors. Note, |
| 34 | /// that the `execvp` syscall independently guarantees that all memory is |
| 35 | /// freed and all file descriptors with the `CLOEXEC` option (set by default |
| 36 | /// on all file descriptors opened by the standard library) are closed. |
| 37 | /// |
| 38 | /// This function, unlike `spawn`, will **not** `fork` the process to create |
| 39 | /// a new child. Like spawn, however, the default behavior for the stdio |
| 40 | /// descriptors will be to inherited from the current process. |
| 41 | /// |
| 42 | /// # Notes |
| 43 | /// |
| 44 | /// The process may be in a "broken state" if this function returns in |
| 45 | /// error. For example the working directory, environment variables, signal |
| 46 | /// handling settings, various user/group information, or aspects of stdio |
| 47 | /// file descriptors may have changed. If a "transactional spawn" is |
| 48 | /// required to gracefully handle errors it is recommended to use the |
| 49 | /// cross-platform `spawn` instead. |
| 50 | fn exec(&mut self) -> io::Error; |
| 51 | |
| 52 | /// Set executable argument |
| 53 | /// |
| 54 | /// Set the first process argument, `argv[0]`, to something other than the |
| 55 | /// default executable path. |
| 56 | fn arg0<S>(&mut self, arg: S) -> &mut Command |
| 57 | where |
| 58 | S: AsRef<OsStr>; |
| 59 | } |
| 60 | |
| 61 | impl crate::sealed::Sealed for Command {} |
| 62 | impl CommandExt for Command { |
| 63 | fn uid(&mut self, id: u32) -> &mut Command { |
| 64 | self.inner.uid(id); |
| 65 | self |
| 66 | } |
| 67 | |
| 68 | fn gid(&mut self, id: u32) -> &mut Command { |
| 69 | self.inner.gid(id); |
| 70 | self |
| 71 | } |
| 72 | |
| 73 | fn exec(&mut self) -> io::Error { |
| 74 | self.inner.exec() |
| 75 | } |
| 76 | |
| 77 | fn arg0<S>(&mut self, arg: S) -> &mut Command |
| 78 | where |
| 79 | S: AsRef<OsStr>, |
| 80 | { |
| 81 | self.inner.arg0(arg); |
| 82 | self |
| 83 | } |
| 84 | } |
| 85 | |