elevated_command/
linux.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
6use crate::Command;
7use anyhow::{anyhow, Result};
8use std::env;
9use std::ffi::OsStr;
10use std::path::PathBuf;
11use std::process::{Command as StdCommand, Output};
12use std::str::FromStr;
13
14/// The implementation of state check and elevated executing varies on each platform
15impl Command {
16    /// Check the state the current program running
17    /// 
18    /// Return `true` if the program is running as root, otherwise false
19    /// 
20    /// # Examples
21    ///
22    /// ```no_run
23    /// use elevated_command::Command;
24    ///
25    /// fn main() {
26    ///     let is_elevated = Command::is_elevated();
27    ///
28    /// }
29    /// ```
30    pub fn is_elevated() -> bool {
31        let uid = unsafe { 
32            libc::getuid()
33        };
34        if uid == 0 { 
35            true 
36        } else { 
37            false 
38        }
39    }
40
41    /// Prompting the user with a graphical OS dialog for the root password, 
42    /// excuting the command with escalated privileges, and return the output
43    /// 
44    /// # Examples
45    ///
46    /// ```no_run
47    /// use elevated_command::Command;
48    /// use std::process::Command as StdCommand;
49    ///
50    /// fn main() {
51    ///     let mut cmd = StdCommand::new("path to the application");
52    ///     let elevated_cmd = Command::new(cmd);
53    ///     let output = elevated_cmd.output().unwrap();
54    /// }
55    /// ```
56    pub fn output(&self) -> Result<Output> {
57        let pkexec = PathBuf::from_str("/bin/pkexec")?;
58        let mut command = StdCommand::new(pkexec);
59        let display = env::var("DISPLAY");
60        let xauthority = env::var("XAUTHORITY");
61        let home = env::var("HOME");
62
63        command.arg("--disable-internal-agent");
64        if display.is_ok() || xauthority.is_ok() || home.is_ok() {
65            command.arg("env");
66            if let Ok(display) = display {
67                command.arg(format!("DISPLAY={}", display));
68            }
69            if let Ok(xauthority) = xauthority {
70                command.arg(format!("XAUTHORITY={}", xauthority));
71            }
72            if let Ok(home) = home {
73                command.arg(format!("HOME={}", home));
74            }
75        } else {
76            if self.cmd.get_envs().any(|(_, v)| v.is_some()) {
77                command.arg("env");
78            }
79        }
80        for (k, v) in self.cmd.get_envs() {
81            if let Some(value) = v {
82                command.arg(format!("{}={}",
83                    k.to_str().ok_or(anyhow!("invalid key"))?,
84                    value.to_str().ok_or(anyhow!("invalid value"))?
85                ));
86            }
87        }
88
89        command.arg(self.cmd.get_program());
90        let args: Vec<&OsStr> = self.cmd.get_args().collect();
91        if !args.is_empty() {
92            command.args(args);
93        }
94
95        let output = command.output()?;
96        Ok(output)
97    }
98}