run_as/lib.rs
1//! This library implements basic support for running a command in an elevated context.
2//!
3//! In particular this runs a command through "sudo" or other platform equivalents.
4//!
5//! ## Basic Usage
6//!
7//! The library provides a single struct called `Command` which largely follows the
8//! API of `std::process::Command`. However it does not support capturing output or
9//! gives any guarantees for the working directory or environment. This is because
10//! the platform APIs do not have support for that either in some cases.
11//!
12//! In particular the working directory is always the system32 folder on windows and
13//! the environment variables are always the ones of the initial system session on
14//! OS X if the GUI mode is used.
15//!
16//! ```rust,no_run
17//! use run_as::Command;
18//!
19//! let status = Command::new("rm")
20//! .arg("/usr/local/my-app")
21//! .status()
22//! .unwrap();
23//! ```
24//!
25//! ## Platform Support
26//!
27//! The following platforms are supported:
28//!
29//! * Windows: always GUI mode
30//! * OS X: GUI and CLI mode
31//! * Linux: GUI and CLI mode
32
33use std::ffi::{OsStr, OsString};
34
35#[cfg(target_os = "macos")]
36mod impl_darwin;
37#[cfg(unix)]
38mod impl_unix;
39#[cfg(windows)]
40mod impl_windows;
41mod restart_self;
42
43pub use crate::restart_self::{restart_self, restart_self_elevated};
44
45#[cfg(unix)]
46pub use crate::impl_unix::is_elevated;
47
48#[cfg(windows)]
49pub use crate::impl_windows::is_elevated;
50
51/// A process builder for elevated execution
52pub struct Command {
53 command: OsString,
54 args: Vec<OsString>,
55 force_prompt: bool,
56 hide: bool,
57 gui: bool,
58 wait_to_complete: bool,
59}
60
61/// The `Command` type acts as a process builder for spawning programs that run in
62/// an elevated context.
63///
64/// Example:
65///
66/// ```rust,no_run
67/// use run_as::Command;
68/// let status = Command::new("cmd").status();
69/// ```
70impl Command {
71 /// Creates a new command type for a given program.
72 ///
73 /// The default configuration is to spawn without arguments, to be visible and
74 /// to not be launched from a GUI context.
75 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
76 Command {
77 command: program.as_ref().to_os_string(),
78 args: vec![],
79 hide: false,
80 gui: false,
81 force_prompt: true,
82 wait_to_complete: true,
83 }
84 }
85
86 /// Add an argument to pass to the program.
87 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
88 self.args.push(arg.as_ref().to_os_string());
89 self
90 }
91
92 /// Add multiple arguments to pass to the program.
93 pub fn args<I, S>(&mut self, args: I) -> &mut Command
94 where
95 I: IntoIterator<Item = S>,
96 S: AsRef<OsStr>,
97 {
98 for arg in args {
99 self.arg(arg.as_ref());
100 }
101 self
102 }
103
104 /// Controls the visibility of the program on supported platforms. The default is
105 /// to launch the program visible.
106 pub fn show(&mut self, val: bool) -> &mut Command {
107 self.hide = !val;
108 self
109 }
110
111 /// Controls the GUI context. The default behavior is to assume that the program is
112 /// launched from a command line (not using a GUI). This primarily controls how the
113 /// elevation prompt is rendered. On some platforms like Windows the elevation prompt
114 /// is always a GUI element.
115 ///
116 /// If the preferred mode is not available it falls back to the other automatically.
117 pub fn gui(&mut self, val: bool) -> &mut Command {
118 self.gui = val;
119 self
120 }
121
122 /// Can disable the prompt forcing for supported platforms. Mostly this allows sudo
123 /// on unix platforms to not prompt for a password.
124 pub fn force_prompt(&mut self, val: bool) -> &mut Command {
125 self.force_prompt = val;
126 self
127 }
128
129 /// Controls whether to wait for the command to complete. The default is to wait.
130 /// If set to false the command is started and the function returns immediately.
131 /// The exit status in that case is always reported as success.
132 pub fn wait_to_complete(&mut self, val: bool) -> &mut Command {
133 self.wait_to_complete = val;
134 self
135 }
136
137 /// Executes a command as a child process, waiting for it to finish and
138 /// collecting its exit status.
139 pub fn status(&mut self) -> std::io::Result<std::process::ExitStatus> {
140 #[cfg(all(unix, target_os = "macos"))]
141 use crate::impl_darwin::runas_impl;
142 #[cfg(all(unix, not(target_os = "macos")))]
143 use impl_unix::runas_impl;
144 #[cfg(windows)]
145 use impl_windows::runas_impl;
146 runas_impl(self)
147 }
148}