runas/lib.rs
1//! This library implements basic support for running a command in an elevated context.
2//!
3//! In particular this runs a command through "sudo" or other platform equivalents.
4//!
5//! ## Basic Usage
6//!
7//! The library provides a single struct called `Command` which largely follows the
8//! API of `std::process::Command`. However it does not support capturing output or
9//! gives any guarantees for the working directory or environment. This is because
10//! the platform APIs do not have support for that either in some cases.
11//!
12//! In particular the working directory is always the system32 folder on windows and
13//! the environment variables are always the ones of the initial system session on
14//! OS X if the GUI mode is used.
15//!
16//! ```rust,no_run
17//! use runas::Command;
18//!
19//! let status = Command::new("rm")
20//! .arg("/usr/local/my-app")
21//! .status()
22//! .unwrap();
23//! ```
24//!
25//! ## Platform Support
26//!
27//! The following platforms are supported:
28//!
29//! * Windows: always GUI mode
30//! * OS X: GUI and CLI mode
31//! * Linux: CLI mode
32use std::ffi::{OsStr, OsString};
33use std::io;
34use std::process::ExitStatus;
35
36#[cfg(target_os = "macos")]
37mod impl_darwin;
38#[cfg(unix)]
39mod impl_unix;
40#[cfg(windows)]
41mod impl_windows;
42
43/// A process builder for elevated execution
44pub struct Command {
45 command: OsString,
46 args: Vec<OsString>,
47 force_prompt: bool,
48 hide: bool,
49 gui: bool,
50}
51
52/// The `Command` type acts as a process builder for spawning programs that run in
53/// an elevated context.
54///
55/// Example:
56///
57/// ```rust,no_run
58/// use runas::Command;
59/// let status = Command::new("cmd").status();
60/// ```
61impl Command {
62 /// Creates a new command type for a given program.
63 ///
64 /// The default configuration is to spawn without arguments, to be visible and
65 /// to not be launched from a GUI context.
66 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
67 Command {
68 command: program.as_ref().to_os_string(),
69 args: vec![],
70 hide: false,
71 gui: false,
72 force_prompt: true,
73 }
74 }
75
76 /// Add an argument to pass to the program.
77 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
78 self.args.push(arg.as_ref().to_os_string());
79 self
80 }
81
82 /// Add multiple arguments to pass to the program.
83
84 pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
85 for arg in args {
86 self.arg(arg);
87 }
88 self
89 }
90
91 /// Controls the visibility of the program on supported platforms. The default is
92 /// to launch the program visible.
93 pub fn show(&mut self, val: bool) -> &mut Command {
94 self.hide = !val;
95 self
96 }
97
98 /// Controls the GUI context. The default behavior is to assume that the program is
99 /// launched from a command line (not using a GUI). This primarily controls how the
100 /// elevation prompt is rendered. On some platforms like Windows the elevation prompt
101 /// is always a GUI element.
102 ///
103 /// If the preferred mode is not available it falls back to the other automatically.
104 pub fn gui(&mut self, val: bool) -> &mut Command {
105 self.gui = val;
106 self
107 }
108
109 /// Can disable the prompt forcing for supported platforms. Mostly this allows sudo
110 /// on unix platforms to not prompt for a password.
111 pub fn force_prompt(&mut self, val: bool) -> &mut Command {
112 self.force_prompt = val;
113 self
114 }
115
116 /// Executes a command as a child process, waiting for it to finish and
117 /// collecting its exit status.
118 pub fn status(&mut self) -> io::Result<ExitStatus> {
119 #[cfg(all(unix, target_os = "macos"))]
120 use crate::impl_darwin::runas_impl;
121 #[cfg(all(unix, not(target_os = "macos")))]
122 use impl_unix::runas_impl;
123 #[cfg(windows)]
124 use impl_windows::runas_impl;
125 runas_impl(self)
126 }
127}