elevated_command/lib.rs
1/*---------------------------------------------------------------------------------------------
2 * Copyright (c) Luis Liu. All rights reserved.
3 * Licensed under the MIT License. See License in the project root for license information.
4 *--------------------------------------------------------------------------------------------*/
5//! [](https://crates.io/crates/elevated-command/)
6//! [](https://docs.rs/elevated-command)
7//!
8//! elevated-command - Run command using `sudo`, prompting the user with a graphical OS dialog if necessary
9use std::convert::From;
10use std::process::Command as StdCommand;
11
12/// Wrap of std::process::command and escalate privileges while executing
13pub struct Command {
14 cmd: StdCommand,
15 #[allow(dead_code)]
16 icon: Option<Vec<u8>>,
17 #[allow(dead_code)]
18 name: Option<String>,
19}
20
21/// Command initialization shares the same logic across all the platforms
22impl Command {
23 /// Constructs a new `Command` from a std::process::Command
24 /// instance, it would read the following configuration from
25 /// the instance while executing:
26 ///
27 /// * The instance's path to the program
28 /// * The instance's arguments
29 /// * The instance's environment variables
30 ///
31 /// So far, the new `Command` would only take the environment variables explicitly
32 /// set by std::process::Command::env and std::process::Command::env,
33 /// without the ones inherited from the parent process
34 ///
35 /// And the environment variables would only be taken on Linux and MacOS,
36 /// they would be ignored on Windows
37 ///
38 /// Current working directory would be the following while executing the command:
39 /// - %SystemRoot%\System32 on Windows
40 /// - /root on Linux
41 /// - $TMPDIR/sudo_prompt_applet/applet.app/Contents/MacOS on MacOS
42 ///
43 /// To pass environment variables on Windows,
44 /// to inherit environment variables from the parent process and
45 /// to change the working directory will be supported in later versions
46 ///
47 /// # Examples
48 ///
49 /// ```no_run
50 /// use elevated_command::Command;
51 /// use std::process::Command as StdCommand;
52 ///
53 /// fn main() {
54 /// let mut cmd = StdCommand::new("path to the application");
55 ///
56 /// cmd.arg("some arg");
57 /// cmd.env("some key", "some value");
58 ///
59 /// let elevated_cmd = Command::new(cmd);
60 /// }
61 /// ```
62 pub fn new(cmd: StdCommand) -> Self {
63 Self {
64 cmd,
65 icon: None,
66 name: None,
67 }
68 }
69
70 /// Consumes the `Take`, returning the wrapped std::process::Command
71 ///
72 /// # Examples
73 ///
74 /// ```no_run
75 /// use elevated_command::Command;
76 /// use std::process::Command as StdCommand;
77 ///
78 /// fn main() {
79 /// let mut cmd = StdCommand::new("path to the application");
80 /// let elevated_cmd = Command::new(cmd);
81 /// let cmd = elevated_cmd.into_inner();
82 /// }
83 /// ```
84 pub fn into_inner(self) -> StdCommand {
85 self.cmd
86 }
87
88 /// Gets a mutable reference to the underlying std::process::Command
89 ///
90 /// # Examples
91 ///
92 /// ```no_run
93 /// use elevated_command::Command;
94 /// use std::process::Command as StdCommand;
95 ///
96 /// fn main() {
97 /// let mut cmd = StdCommand::new("path to the application");
98 /// let elevated_cmd = Command::new(cmd);
99 /// let cmd = elevated_cmd.get_ref();
100 /// }
101 /// ```
102 pub fn get_ref(&self) -> &StdCommand {
103 &self.cmd
104 }
105
106 /// Gets a reference to the underlying std::process::Command
107 ///
108 /// # Examples
109 ///
110 /// ```no_run
111 /// use elevated_command::Command;
112 /// use std::process::Command as StdCommand;
113 ///
114 /// fn main() {
115 /// let mut cmd = StdCommand::new("path to the application");
116 /// let elevated_cmd = Command::new(cmd);
117 /// let cmd = elevated_cmd.get_mut();
118 /// }
119 /// ```
120 pub fn get_mut(&mut self) -> &mut StdCommand {
121 &mut self.cmd
122 }
123
124 /// Set the `icon` for the pop-up graphical OS dialog
125 ///
126 /// This method is only applicable on `MacOS`
127 ///
128 /// # Examples
129 ///
130 /// ```no_run
131 /// use elevated_command::Command;
132 /// use std::process::Command as StdCommand;
133 ///
134 /// fn main() {
135 /// let mut cmd = StdCommand::new("path to the application");
136 /// let elevated_cmd = Command::new(cmd);
137 /// elevated_cmd.icon(include_bytes!("path to the icon").to_vec());
138 /// }
139 /// ```
140 pub fn icon(&mut self, icon: Vec<u8>) -> &mut Self {
141 self.icon = Some(icon);
142 self
143 }
144
145 /// Set the name for the pop-up graphical OS dialog
146 ///
147 /// This method is only applicable on `MacOS`
148 ///
149 /// # Examples
150 ///
151 /// ```no_run
152 /// use elevated_command::Command;
153 /// use std::process::Command as StdCommand;
154 ///
155 /// fn main() {
156 /// let mut cmd = StdCommand::new("path to the application");
157 /// let elevated_cmd = Command::new(cmd);
158 /// elevated_cmd.name("some name".to_string());
159 /// }
160 /// ```
161 pub fn name(&mut self, name: String) -> &mut Self {
162 self.name = Some(name);
163 self
164 }
165}
166
167impl From<StdCommand> for Command {
168 /// Converts from a std::process::Command
169 ///
170 /// It is similiar with the construct method
171 fn from(cmd: StdCommand) -> Self {
172 Self {
173 cmd,
174 icon: None,
175 name: None,
176 }
177 }
178}
179
180#[cfg(target_os = "windows")]
181mod windows;
182#[cfg(target_os = "linux")]
183mod linux;
184#[cfg(target_os = "macos")]
185mod macos;