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//! [![crates.io](https://img.shields.io/crates/v/elevated-command?logo=rust)](https://crates.io/crates/elevated-command/)
6//! [![docs.rs](https://docs.rs/elevated-command/badge.svg)](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;