3 // ignore-emscripten no processes
4 // ignore-sgx no processes
6 #![feature(rustc_private)]
10 use std
::process
::{Command, Stdio}
;
12 use std
::io
::{self, Read, Write}
;
15 unsafe fn without_stdio
<R
, F
: FnOnce() -> R
>(f
: F
) -> R
{
25 assert
!(libc
::close(0) >= 0);
26 assert
!(libc
::close(1) >= 0);
27 assert
!(libc
::close(2) >= 0);
31 assert
!(libc
::dup2(a
, 0) >= 0);
32 assert
!(libc
::dup2(b
, 1) >= 0);
33 assert
!(libc
::dup2(c
, 2) >= 0);
39 fn assert_fd_is_valid(fd
: libc
::c_int
) {
40 if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 }
{
41 panic
!("file descriptor {} is not valid: {}", fd
, io
::Error
::last_os_error());
46 fn assert_fd_is_valid(_fd
: libc
::c_int
) {}
49 unsafe fn without_stdio
<R
, F
: FnOnce() -> R
>(f
: F
) -> R
{
51 type HANDLE
= *mut u8;
54 const STD_INPUT_HANDLE
: DWORD
= -10i32 as DWORD
;
55 const STD_OUTPUT_HANDLE
: DWORD
= -11i32 as DWORD
;
56 const STD_ERROR_HANDLE
: DWORD
= -12i32 as DWORD
;
57 const INVALID_HANDLE_VALUE
: HANDLE
= !0 as HANDLE
;
60 fn GetStdHandle(which
: DWORD
) -> HANDLE
;
61 fn SetStdHandle(which
: DWORD
, handle
: HANDLE
) -> BOOL
;
65 let handle
= GetStdHandle(id
);
66 assert
!(handle
!= INVALID_HANDLE_VALUE
);
67 assert
!(SetStdHandle(id
, INVALID_HANDLE_VALUE
) != 0);
71 let a
= doit(STD_INPUT_HANDLE
);
72 let b
= doit(STD_OUTPUT_HANDLE
);
73 let c
= doit(STD_ERROR_HANDLE
);
77 let doit
= |id
, handle
| {
78 assert
!(SetStdHandle(id
, handle
) != 0);
80 doit(STD_INPUT_HANDLE
, a
);
81 doit(STD_OUTPUT_HANDLE
, b
);
82 doit(STD_ERROR_HANDLE
, c
);
88 if env
::args().len() > 1 {
89 // Writing to stdout & stderr should not panic.
91 assert
!(io
::stdout().write(b
"test\n").is_ok());
92 assert
!(io
::stderr().write(b
"test\n").is_ok());
94 // Stdin should be at EOF.
95 assert_eq
!(io
::stdin().read(&mut [0; 10]).unwrap(), 0);
97 // Standard file descriptors should be valid on UNIX:
98 assert_fd_is_valid(0);
99 assert_fd_is_valid(1);
100 assert_fd_is_valid(2);
104 // First, make sure reads/writes without stdio work if stdio itself is
106 let (a
, b
, c
) = unsafe {
108 let a
= io
::stdout().write(b
"test\n");
109 let b
= io
::stderr().write(b
"test\n");
110 let c
= io
::stdin().read(&mut [0; 10]);
116 assert_eq
!(a
.unwrap(), 5);
117 assert_eq
!(b
.unwrap(), 5);
118 assert_eq
!(c
.unwrap(), 0);
120 // Second, spawn a child and do some work with "null" descriptors to make
122 let me
= env
::current_exe().unwrap();
123 let status
= Command
::new(&me
)
125 .stdin(Stdio
::null())
126 .stdout(Stdio
::null())
127 .stderr(Stdio
::null())
129 assert
!(status
.success(), "{} isn't a success", status
);
131 // Finally, close everything then spawn a child to make sure everything is
133 let status
= unsafe {
134 without_stdio(|| Command
::new(&me
).arg("next").status())
136 assert
!(status
.success(), "{} isn't a success", status
);