1use std::fs::File;
2use std::io;
3use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
4
5use libc::c_int;
6use libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
7
8pub(crate) use std::os::unix::io::{AsRawFd as AsRaw, IntoRawFd as IntoRaw, RawFd as Raw};
9
10pub(crate) fn as_raw(io: &impl AsRawFd) -> RawFd {
11 io.as_raw_fd()
12}
13pub(crate) fn into_raw(io: impl IntoRawFd) -> RawFd {
14 io.into_raw_fd()
15}
16
17pub(crate) fn override_stdin(io: RawFd, owned: bool) -> io::Result<File> {
18 override_stdio(STDIN_FILENO, io, owned)
19}
20pub(crate) fn override_stdout(io: RawFd, owned: bool) -> io::Result<File> {
21 override_stdio(STDOUT_FILENO, io, owned)
22}
23pub(crate) fn override_stderr(io: RawFd, owned: bool) -> io::Result<File> {
24 override_stdio(STDERR_FILENO, io, owned)
25}
26
27pub(crate) fn reset_stdin(old: RawFd) -> io::Result<()> {
28 set_stdio(STDIN_FILENO, old)
29}
30pub(crate) fn reset_stdout(old: RawFd) -> io::Result<()> {
31 set_stdio(STDOUT_FILENO, old)
32}
33pub(crate) fn reset_stderr(old: RawFd) -> io::Result<()> {
34 set_stdio(STDERR_FILENO, old)
35}
36
37fn override_stdio(stdio: RawFd, other: RawFd, owned: bool) -> io::Result<File> {
38 let original = io_res(unsafe { libc::dup(stdio) })?;
39 set_stdio(stdio, other)?;
40
41 if owned {
42 io_res(unsafe { libc::close(other) })?;
43 }
44
45 Ok(unsafe { File::from_raw_fd(original) })
46}
47
48fn set_stdio(stdio: RawFd, other: RawFd) -> io::Result<()> {
49 io_res(unsafe { libc::dup2(other, stdio) })?;
50 Ok(())
51}
52
53#[cfg(test)]
54#[test]
55fn test_original() -> io::Result<()> {
56 use std::io::{Read, Write};
57
58 let (mut rx, tx) = os_pipe::pipe()?;
59
60 let real_stdout = override_stdio(STDOUT_FILENO, tx.into_raw_fd(), true)?.into_raw_fd();
61
62 println!("Let's see where it's saved");
63 io::stdout().lock().flush()?;
64
65 set_stdio(STDOUT_FILENO, real_stdout)?;
66
67 let mut contents = String::new();
68 rx.read_to_string(&mut contents)?;
69 assert_eq!("Let\'s see where it\'s saved\n", contents);
70
71 println!("got back");
72
73 Ok(())
74}
75
76fn io_res(res: c_int) -> io::Result<c_int> {
77 if res == -1 {
78 Err(io::Error::last_os_error())
79 } else {
80 Ok(res)
81 }
82}
83
84impl AsRawFd for crate::StdinOverride {
85 fn as_raw_fd(&self) -> RawFd {
86 self.original.as_raw_fd()
87 }
88}
89impl AsRawFd for crate::StdoutOverride {
90 fn as_raw_fd(&self) -> RawFd {
91 self.original.as_raw_fd()
92 }
93}
94impl AsRawFd for crate::StderrOverride {
95 fn as_raw_fd(&self) -> RawFd {
96 self.original.as_raw_fd()
97 }
98}