1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 // ignore-cloudabi no processes
13 // ignore-emscripten no processes
19 use std::process::{Command, Stdio};
21 use std::io::{self, Read, Write};
24 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
34 assert!(libc::close(0) >= 0);
35 assert!(libc::close(1) >= 0);
36 assert!(libc::close(2) >= 0);
40 assert!(libc::dup2(a, 0) >= 0);
41 assert!(libc::dup2(b, 1) >= 0);
42 assert!(libc::dup2(c, 2) >= 0);
48 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
50 type HANDLE = *mut u8;
53 const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
54 const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
55 const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
56 const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
59 fn GetStdHandle(which: DWORD) -> HANDLE;
60 fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL;
64 let handle = GetStdHandle(id);
65 assert!(handle != INVALID_HANDLE_VALUE);
66 assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0);
70 let a = doit(STD_INPUT_HANDLE);
71 let b = doit(STD_OUTPUT_HANDLE);
72 let c = doit(STD_ERROR_HANDLE);
76 let doit = |id, handle| {
77 assert!(SetStdHandle(id, handle) != 0);
79 doit(STD_INPUT_HANDLE, a);
80 doit(STD_OUTPUT_HANDLE, b);
81 doit(STD_ERROR_HANDLE, c);
87 if env::args().len() > 1 {
89 assert!(io::stdout().write(b"test\n").is_ok());
90 assert!(io::stderr().write(b"test\n").is_ok());
91 assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0);
95 // First, make sure reads/writes without stdio work if stdio itself is
97 let (a, b, c) = unsafe {
99 let a = io::stdout().write(b"test\n");
100 let b = io::stderr().write(b"test\n");
101 let c = io::stdin().read(&mut [0; 10]);
107 assert_eq!(a.unwrap(), 5);
108 assert_eq!(b.unwrap(), 5);
109 assert_eq!(c.unwrap(), 0);
111 // Second, spawn a child and do some work with "null" descriptors to make
113 let me = env::current_exe().unwrap();
114 let status = Command::new(&me)
116 .stdin(Stdio::null())
117 .stdout(Stdio::null())
118 .stderr(Stdio::null())
120 assert!(status.success(), "{:?} isn't a success", status);
122 // Finally, close everything then spawn a child to make sure everything is
124 let status = unsafe {
125 without_stdio(|| Command::new(&me).arg("next").status())
127 assert!(status.success(), "{:?} isn't a success", status);