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 /// 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;