redirect_stdout/
lib.rs

1// #[cfg(target_family = "unix")]
2// fn get_stdout() -> Result<RawFd, Error> {
3//     use std::os::unix::io::AsRawFd;
4//     use std::io::stdout;
5//     Ok(stdout().as_raw_fd())
6// }
7
8// #[cfg(target_family = "windows")]
9// fn get_stdout() -> Result<std::os::windows::io::RawHandle, dyn
10// std::error::Error> {     use std::io::stdout;
11//     Ok(stdout().as_raw_handle())
12// }
13
14// use std::os::fd::FromRawFd as _;
15#[cfg(target_family = "windows")]
16static mut WINAPI_STDERR_HANDLE: *mut winapi::ctypes::c_void =
17  std::ptr::null_mut();
18#[cfg(not(target_os = "windows"))]
19static mut UNIX_STDERR_HANDLE: i32 = -1;
20
21#[cfg(target_family = "windows")]
22static mut WINAPI_STDOUT_HANDLE: *mut winapi::ctypes::c_void =
23  std::ptr::null_mut();
24#[cfg(not(target_os = "windows"))]
25static mut UNIX_STDOUT_HANDLE: i32 = -1;
26
27pub fn redirect_stderr() -> std::io::Result<()> {
28  use std::fs::File;
29  use std::io::{self};
30
31  #[allow(unused_variables)]
32  let dev_null = if cfg!(target_os = "windows") {
33    File::create("NUL")?
34  } else {
35    File::create("/dev/null")?
36  };
37
38  #[cfg(target_os = "windows")]
39  {
40    use std::os::windows::io::AsRawHandle;
41    use winapi::um::handleapi::SetHandleInformation;
42    use winapi::um::processenv::SetStdHandle;
43    use winapi::um::winbase::{HANDLE_FLAG_INHERIT, STD_ERROR_HANDLE};
44
45    unsafe {
46      // Ensure the handle is not inherited
47      let handle = dev_null.as_raw_handle() as *mut winapi::ctypes::c_void;
48      SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
49
50      if (WINAPI_STDERR_HANDLE != handle) {
51        WINAPI_STDERR_HANDLE =
52          std::io::stdout().as_raw_handle() as *mut winapi::ctypes::c_void;
53      }
54
55      // Redirect stderr to NUL
56      if SetStdHandle(STD_ERROR_HANDLE, handle) == 0 {
57        return Err(io::Error::last_os_error());
58      }
59    }
60  }
61
62  #[cfg(not(target_os = "windows"))]
63  {
64    use libc;
65    use std::os::unix::io::AsRawFd;
66
67    unsafe {
68      let raw_fd = dev_null.as_raw_fd();
69
70      if (UNIX_STDERR_HANDLE != raw_fd) {
71        UNIX_STDERR_HANDLE = std::io::stdout().as_raw_fd();
72      }
73
74      if libc::dup2(raw_fd, libc::STDERR_FILENO) == -1 {
75        return Err(io::Error::last_os_error());
76      }
77    }
78  }
79
80  Ok(())
81}
82
83pub fn restore_stderr() -> std::io::Result<()> {
84  use std::fs::File;
85  use std::io::{self};
86
87  #[cfg(target_os = "windows")]
88  {
89    use std::os::windows::io::AsRawHandle;
90    use winapi::um::handleapi::SetHandleInformation;
91    use winapi::um::processenv::SetStdHandle;
92    use winapi::um::winbase::{HANDLE_FLAG_INHERIT, STD_ERROR_HANDLE};
93
94    unsafe {
95      if SetStdHandle(STD_ERROR_HANDLE, WINAPI_STDERR_HANDLE) == 0 {
96        return Err(io::Error::last_os_error());
97      }
98    }
99  }
100
101  #[cfg(not(target_os = "windows"))]
102  {
103    use libc;
104    use std::os::unix::io::AsRawFd;
105
106    unsafe {
107      if libc::dup2(UNIX_STDERR_HANDLE, libc::STDERR_FILENO) == -1 {
108        return Err(io::Error::last_os_error());
109      }
110    }
111  }
112
113  Ok(())
114}
115
116pub fn redirect_stdout() -> std::io::Result<()> {
117  use std::fs::File;
118  use std::io::{self};
119
120  #[allow(unused_variables)]
121  let dev_null = if cfg!(target_os = "windows") {
122    File::create("NUL")?
123  } else {
124    File::create("/dev/null")?
125  };
126
127  #[cfg(target_os = "windows")]
128  {
129    use std::os::windows::io::AsRawHandle;
130    use winapi::um::handleapi::SetHandleInformation;
131    use winapi::um::processenv::SetStdHandle;
132    use winapi::um::winbase::{HANDLE_FLAG_INHERIT, STD_OUTPUT_HANDLE};
133
134    unsafe {
135      // Ensure the handle is not inherited
136      let handle = dev_null.as_raw_handle() as *mut winapi::ctypes::c_void;
137      SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
138
139      if (WINAPI_STDOUT_HANDLE != handle) {
140        WINAPI_STDOUT_HANDLE =
141          std::io::stdout().as_raw_handle() as *mut winapi::ctypes::c_void;
142      }
143
144      // Redirect stderr to NUL
145      if SetStdHandle(STD_OUTPUT_HANDLE, handle) == 0 {
146        return Err(io::Error::last_os_error());
147      }
148    }
149  }
150
151  #[cfg(not(target_os = "windows"))]
152  {
153    use libc;
154    use std::os::unix::io::AsRawFd;
155
156    // Save the original stdout
157    let stdout = io::stdout();
158    let original_fd = stdout.as_raw_fd();
159
160    // Redirect stdout to /dev/null
161    let dev_null_fd = File::open("/dev/null").unwrap().as_raw_fd();
162
163    unsafe {
164      if (UNIX_STDOUT_HANDLE != dev_null_fd) {
165        UNIX_STDOUT_HANDLE = libc::dup(original_fd);
166      }
167
168      libc::dup2(dev_null_fd, original_fd);
169    }
170
171    // unsafe {
172    //   let raw_fd = dev_null.as_raw_fd();
173
174    //   if (UNIX_STDOUT_HANDLE != raw_fd) {
175    //     UNIX_STDOUT_HANDLE = std::io::stdout().as_raw_fd();
176    //   }
177
178    //   if libc::dup2(raw_fd, libc::STDOUT_FILENO) == -1 {
179    //     return Err(io::Error::last_os_error());
180    //   }
181    // }
182  }
183
184  Ok(())
185}
186
187pub fn restore_stdout() -> std::io::Result<()> {
188  use std::fs::File;
189  use std::io::{self};
190
191  #[cfg(target_os = "windows")]
192  {
193    use std::os::windows::io::AsRawHandle;
194    use winapi::um::handleapi::SetHandleInformation;
195    use winapi::um::processenv::SetStdHandle;
196    use winapi::um::winbase::{HANDLE_FLAG_INHERIT, STD_OUTPUT_HANDLE};
197
198    unsafe {
199      if SetStdHandle(STD_OUTPUT_HANDLE, WINAPI_STDOUT_HANDLE) == 0 {
200        return Err(io::Error::last_os_error());
201      }
202    }
203  }
204
205  #[cfg(not(target_os = "windows"))]
206  {
207    use libc;
208    use std::os::unix::io::AsRawFd;
209
210    // Save the original stdout
211    let stdout = io::stdout();
212    let original_fd = stdout.as_raw_fd();
213
214    unsafe {
215      libc::dup2(UNIX_STDOUT_HANDLE, original_fd);
216    }
217  }
218
219  Ok(())
220}