Skip to main content

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    /// let mut cmd = StdCommand::new("path to the application");
54    ///
55    /// cmd.arg("some arg");
56    /// cmd.env("some key", "some value");
57    ///
58    /// let elevated_cmd = Command::new(cmd);
59    /// ```
60    pub fn new(cmd: StdCommand) -> Self {
61        Self {
62            cmd,
63            icon: None,
64            name: None,
65        }
66    }
67
68    /// Consumes the `Take`, returning the wrapped std::process::Command
69    ///
70    /// # Examples
71    ///
72    /// ```no_run
73    /// use elevated_command::Command;
74    /// use std::process::Command as StdCommand;
75    ///
76    /// let mut cmd = StdCommand::new("path to the application");
77    /// let elevated_cmd = Command::new(cmd);
78    /// let cmd = elevated_cmd.into_inner();
79    /// ```
80    pub fn into_inner(self) -> StdCommand {
81        self.cmd
82    }
83
84    /// Gets a mutable reference to the underlying std::process::Command
85    ///
86    /// # Examples
87    ///
88    /// ```no_run
89    /// use elevated_command::Command;
90    /// use std::process::Command as StdCommand;
91    ///
92    /// let mut cmd = StdCommand::new("path to the application");
93    /// let elevated_cmd = Command::new(cmd);
94    /// let cmd = elevated_cmd.get_ref();
95    /// ```
96    pub fn get_ref(&self) -> &StdCommand {
97        &self.cmd
98    }
99
100    /// Gets a reference to the underlying std::process::Command
101    ///
102    /// # Examples
103    ///
104    /// ```no_run
105    /// use elevated_command::Command;
106    /// use std::process::Command as StdCommand;
107    ///
108    /// let mut cmd = StdCommand::new("path to the application");
109    /// let mut elevated_cmd = Command::new(cmd);
110    /// let cmd = elevated_cmd.get_mut();
111    /// ```
112    pub fn get_mut(&mut self) -> &mut StdCommand {
113        &mut self.cmd
114    }
115
116    /// Set the `icon` for the pop-up graphical OS dialog
117    ///
118    /// This method is only applicable on `MacOS`
119    ///
120    /// # Examples
121    ///
122    /// ```rust,ignore,no_run
123    /// use elevated_command::Command;
124    /// use std::process::Command as StdCommand;
125    ///
126    /// let mut cmd = StdCommand::new("path to the application");
127    /// let elevated_cmd = Command::new(cmd);
128    /// elevated_cmd.icon(include_bytes!("path to the icon").to_vec());
129    /// ```
130    pub fn icon(&mut self, icon: Vec<u8>) -> &mut Self {
131        self.icon = Some(icon);
132        self
133    }
134
135    /// Set the name for the pop-up graphical OS dialog
136    ///
137    /// This method is only applicable on `MacOS`
138    ///
139    /// # Examples
140    ///
141    /// ```no_run
142    /// use elevated_command::Command;
143    /// use std::process::Command as StdCommand;
144    ///
145    /// let mut cmd = StdCommand::new("path to the application");
146    /// let mut elevated_cmd = Command::new(cmd);
147    /// elevated_cmd.name("some name".to_string());
148    /// ```
149    pub fn name(&mut self, name: String) -> &mut Self {
150        self.name = Some(name);
151        self
152    }
153}
154
155impl From<StdCommand> for Command {
156    /// Converts from a std::process::Command
157    ///
158    /// It is similiar with the construct method
159    fn from(cmd: StdCommand) -> Self {
160        Self {
161            cmd,
162            icon: None,
163            name: None,
164        }
165    }
166}
167
168#[cfg(target_os = "linux")]
169mod linux;
170#[cfg(target_os = "macos")]
171mod macos;
172#[cfg(target_os = "windows")]
173mod windows;