diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-02-06 22:38:05 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-02-16 16:01:03 -0800 |
| commit | 553b7e67d70dbf72dd705616acaa496a20fba765 (patch) | |
| tree | 4274ee5030cea6f05dbbb23f75c1c9eb4e58c2f1 /src/libstd/io/process.rs | |
| parent | 13dc521861f6c3be909ba9317fde50f946e9f85d (diff) | |
| download | rust-553b7e67d70dbf72dd705616acaa496a20fba765.tar.gz rust-553b7e67d70dbf72dd705616acaa496a20fba765.zip | |
Allow configuration of uid/gid/detach on processes
This just copies the libuv implementation for libnative which seems reasonable enough (uid/gid fail on windows). Closes #12082
Diffstat (limited to 'src/libstd/io/process.rs')
| -rw-r--r-- | src/libstd/io/process.rs | 129 |
1 files changed, 106 insertions, 23 deletions
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index b515cd9d31c..6540fcd85d3 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -58,7 +58,21 @@ pub struct ProcessConfig<'a> { /// 0 - stdin /// 1 - stdout /// 2 - stderr - io: &'a [StdioContainer] + io: &'a [StdioContainer], + + /// Sets the child process's user id. This translates to a `setuid` call in + /// the child process. Setting this value on windows will cause the spawn to + /// fail. Failure in the `setuid` call on unix will also cause the spawn to + /// fail. + uid: Option<uint>, + + /// Similar to `uid`, but sets the group id of the child process. This has + /// the same semantics as the `uid` field. + gid: Option<uint>, + + /// If true, the child process is spawned in a detached state. On unix, this + /// means that the child is the leader of a new process group. + detach: bool, } /// Describes what to do with a standard io stream for a child process. @@ -115,6 +129,36 @@ impl ProcessExit { } } +impl<'a> ProcessConfig<'a> { + /// Creates a new configuration with blanks as all of the defaults. This is + /// useful when using functional struct updates: + /// + /// ```rust + /// use std::io::process::{ProcessConfig, Process}; + /// + /// let config = ProcessConfig { + /// program: "/bin/sh", + /// args: &'static [~"-c", ~"echo hello"], + /// .. ProcessConfig::new() + /// }; + /// + /// let p = Process::new(config); + /// ``` + /// + pub fn new() -> ProcessConfig<'static> { + ProcessConfig { + program: "", + args: &'static [], + env: None, + cwd: None, + io: &'static [], + uid: None, + gid: None, + detach: false, + } + } +} + impl Process { /// Creates a new pipe initialized, but not bound to any particular /// source/destination @@ -175,13 +219,10 @@ mod tests { // FIXME(#10380) #[cfg(unix, not(target_os="android"))] iotest!(fn smoke() { - let io = ~[]; let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"true"], - env: None, - cwd: None, - io: io, + .. ProcessConfig::new() }; let p = Process::new(args); assert!(p.is_ok()); @@ -192,13 +233,9 @@ mod tests { // FIXME(#10380) #[cfg(unix, not(target_os="android"))] iotest!(fn smoke_failure() { - let io = ~[]; let args = ProcessConfig { program: "if-this-is-a-binary-then-the-world-has-ended", - args: &[], - env: None, - cwd: None, - io: io, + .. ProcessConfig::new() }; match Process::new(args) { Ok(..) => fail!(), @@ -209,13 +246,10 @@ mod tests { // FIXME(#10380) #[cfg(unix, not(target_os="android"))] iotest!(fn exit_reported_right() { - let io = ~[]; let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"exit 1"], - env: None, - cwd: None, - io: io, + .. ProcessConfig::new() }; let p = Process::new(args); assert!(p.is_ok()); @@ -225,13 +259,10 @@ mod tests { #[cfg(unix, not(target_os="android"))] iotest!(fn signal_reported_right() { - let io = ~[]; let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"kill -1 $$"], - env: None, - cwd: None, - io: io, + .. ProcessConfig::new() }; let p = Process::new(args); assert!(p.is_ok()); @@ -264,9 +295,8 @@ mod tests { let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"echo foobar"], - env: None, - cwd: None, io: io, + .. ProcessConfig::new() }; assert_eq!(run_output(args), ~"foobar\n"); }) @@ -279,9 +309,9 @@ mod tests { let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"pwd"], - env: None, cwd: cwd, io: io, + .. ProcessConfig::new() }; assert_eq!(run_output(args), ~"/\n"); }) @@ -294,9 +324,8 @@ mod tests { let args = ProcessConfig { program: "/bin/sh", args: &[~"-c", ~"read line; echo $line"], - env: None, - cwd: None, io: io, + .. ProcessConfig::new() }; let mut p = Process::new(args).unwrap(); p.io[0].get_mut_ref().write("foobar".as_bytes()).unwrap(); @@ -306,4 +335,58 @@ mod tests { assert_eq!(out, ~"foobar\n"); }) + // FIXME(#10380) + #[cfg(unix, not(target_os="android"))] + iotest!(fn detach_works() { + let args = ProcessConfig { + program: "/bin/sh", + args: &[~"-c", ~"true"], + detach: true, + .. ProcessConfig::new() + }; + let mut p = Process::new(args).unwrap(); + assert!(p.wait().success()); + }) + + #[cfg(windows)] + iotest!(fn uid_fails_on_windows() { + let args = ProcessConfig { + program: "test", + uid: Some(10), + .. ProcessConfig::new() + }; + assert!(Process::new(args).is_err()); + }) + + // FIXME(#10380) + #[cfg(unix, not(target_os="android"))] + iotest!(fn uid_works() { + use libc; + let args = ProcessConfig { + program: "/bin/sh", + args: &[~"-c", ~"true"], + uid: Some(unsafe { libc::getuid() as uint }), + gid: Some(unsafe { libc::getgid() as uint }), + .. ProcessConfig::new() + }; + let mut p = Process::new(args).unwrap(); + assert!(p.wait().success()); + }) + + // FIXME(#10380) + #[cfg(unix, not(target_os="android"))] + iotest!(fn uid_to_root_fails() { + use libc; + + // if we're already root, this isn't a valid test. Most of the bots run + // as non-root though (android is an exception). + if unsafe { libc::getuid() == 0 } { return } + let args = ProcessConfig { + program: "/bin/ls", + uid: Some(0), + gid: Some(0), + .. ProcessConfig::new() + }; + assert!(Process::new(args).is_err()); + }) } |
