use ffi::OsStr;
use fmt;
+use fs;
use io;
use path::Path;
use str;
/// .expect("ls command failed to start");
/// ```
#[stable(feature = "process", since = "1.0.0")]
- pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
- self.inner.stdin(cfg.0);
+ pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
+ self.inner.stdin(cfg.into().0);
self
}
/// .expect("ls command failed to start");
/// ```
#[stable(feature = "process", since = "1.0.0")]
- pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
- self.inner.stdout(cfg.0);
+ pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
+ self.inner.stdout(cfg.into().0);
self
}
/// .expect("ls command failed to start");
/// ```
#[stable(feature = "process", since = "1.0.0")]
- pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
- self.inner.stderr(cfg.0);
+ pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
+ self.inner.stderr(cfg.into().0);
self
}
}
}
+#[stable(feature = "stdio_from", since = "1.20.0")]
+impl From<ChildStdin> for Stdio {
+ fn from(child: ChildStdin) -> Stdio {
+ Stdio::from_inner(child.into_inner().into())
+ }
+}
+
+#[stable(feature = "stdio_from", since = "1.20.0")]
+impl From<ChildStdout> for Stdio {
+ fn from(child: ChildStdout) -> Stdio {
+ Stdio::from_inner(child.into_inner().into())
+ }
+}
+
+#[stable(feature = "stdio_from", since = "1.20.0")]
+impl From<ChildStderr> for Stdio {
+ fn from(child: ChildStderr) -> Stdio {
+ Stdio::from_inner(child.into_inner().into())
+ }
+}
+
+#[stable(feature = "stdio_from", since = "1.20.0")]
+impl From<fs::File> for Stdio {
+ fn from(file: fs::File) -> Stdio {
+ Stdio::from_inner(file.into_inner().into())
+ }
+}
+
/// Describes the result of a process after it has terminated.
///
/// This `struct` is used to represent the exit status of a child process.
}
}
+impl From<AnonPipe> for Stdio {
+ fn from(pipe: AnonPipe) -> Stdio {
+ Stdio::Fd(pipe.into_fd())
+ }
+}
+
+impl From<File> for Stdio {
+ fn from(file: File) -> Stdio {
+ Stdio::Fd(file.into_fd())
+ }
+}
+
impl ChildStdio {
fn fd(&self) -> Option<usize> {
match *self {
}
}
+impl From<AnonPipe> for Stdio {
+ fn from(pipe: AnonPipe) -> Stdio {
+ Stdio::Fd(pipe.into_fd())
+ }
+}
+
+impl From<File> for Stdio {
+ fn from(file: File) -> Stdio {
+ Stdio::Fd(file.into_fd())
+ }
+}
+
impl ChildStdio {
pub fn fd(&self) -> Option<c_int> {
match *self {
}
}
+impl From<AnonPipe> for Stdio {
+ fn from(pipe: AnonPipe) -> Stdio {
+ Stdio::Handle(pipe.into_handle())
+ }
+}
+
+impl From<File> for Stdio {
+ fn from(file: File) -> Stdio {
+ Stdio::Handle(file.into_handle())
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Processes
////////////////////////////////////////////////////////////////////////////////
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-cross-compile
+
+#![feature(rustc_private)]
+
+extern crate rustc_back;
+
+use std::env;
+use std::fs::File;
+use std::io;
+use std::io::{Read, Write};
+use std::process::{Command, Stdio};
+
+use rustc_back::tempdir::TempDir;
+
+fn main() {
+ if env::args().len() > 1 {
+ child().unwrap()
+ } else {
+ parent().unwrap()
+ }
+}
+
+fn parent() -> io::Result<()> {
+ let td = TempDir::new("foo").unwrap();
+ let input = td.path().join("input");
+ let output = td.path().join("output");
+
+ File::create(&input)?.write_all(b"foo\n")?;
+
+ // Set up this chain:
+ // $ me <file | me | me >file
+ // ... to duplicate each line 8 times total.
+
+ let mut child1 = Command::new(env::current_exe()?)
+ .arg("first")
+ .stdin(File::open(&input)?) // tests File::into()
+ .stdout(Stdio::piped())
+ .spawn()?;
+
+ let mut child3 = Command::new(env::current_exe()?)
+ .arg("third")
+ .stdin(Stdio::piped())
+ .stdout(File::create(&output)?) // tests File::into()
+ .spawn()?;
+
+ // Started out of order so we can test both `ChildStdin` and `ChildStdout`.
+ let mut child2 = Command::new(env::current_exe()?)
+ .arg("second")
+ .stdin(child1.stdout.take().unwrap()) // tests ChildStdout::into()
+ .stdout(child3.stdin.take().unwrap()) // tests ChildStdin::into()
+ .spawn()?;
+
+ assert!(child1.wait()?.success());
+ assert!(child2.wait()?.success());
+ assert!(child3.wait()?.success());
+
+ let mut data = String::new();
+ File::open(&output)?.read_to_string(&mut data)?;
+ for line in data.lines() {
+ assert_eq!(line, "foo");
+ }
+ assert_eq!(data.lines().count(), 8);
+ Ok(())
+}
+
+fn child() -> io::Result<()> {
+ // double everything
+ let mut input = vec![];
+ io::stdin().read_to_end(&mut input)?;
+ io::stdout().write_all(&input)?;
+ io::stdout().write_all(&input)?;
+ Ok(())
+}
Command::new(name)
.arg("--child")
.stdin(Stdio::inherit())
- .stdout(unsafe { FromRawFd::from_raw_fd(libc::STDERR_FILENO) })
- .stderr(unsafe { FromRawFd::from_raw_fd(libc::STDOUT_FILENO) })
+ .stdout(unsafe { Stdio::from_raw_fd(libc::STDERR_FILENO) })
+ .stderr(unsafe { Stdio::from_raw_fd(libc::STDOUT_FILENO) })
.spawn()
};