#[cfg(unix)]
mod imp {
use std::os::fd::AsRawFd;
use std::sync::atomic::{AtomicI32, Ordering};
static SAVED: AtomicI32 = AtomicI32::new(-1);
pub fn silence() {
if SAVED.load(Ordering::Relaxed) >= 0 {
return;
}
let saved = unsafe { libc::dup(2) };
if saved < 0 {
return;
}
let null = match std::fs::OpenOptions::new().write(true).open("/dev/null") {
Ok(f) => f,
Err(_) => {
unsafe { libc::close(saved) };
return;
}
};
unsafe { libc::dup2(null.as_raw_fd(), 2) };
SAVED.store(saved, Ordering::Relaxed);
}
pub fn restore() {
let saved = SAVED.swap(-1, Ordering::Relaxed);
if saved >= 0 {
unsafe {
libc::dup2(saved, 2);
libc::close(saved);
}
}
}
}
#[cfg(windows)]
mod imp {
use std::os::windows::io::IntoRawHandle;
use std::sync::atomic::{AtomicIsize, Ordering};
const STD_ERROR_HANDLE: u32 = 0xFFFF_FFF4;
unsafe extern "system" {
fn GetStdHandle(n_std_handle: u32) -> isize;
fn SetStdHandle(n_std_handle: u32, h_handle: isize) -> i32;
fn CloseHandle(h_handle: isize) -> i32;
}
static SAVED: AtomicIsize = AtomicIsize::new(0);
static NULL: AtomicIsize = AtomicIsize::new(0);
pub fn silence() {
if SAVED.load(Ordering::Relaxed) != 0 {
return;
}
let saved = unsafe { GetStdHandle(STD_ERROR_HANDLE) };
if saved == 0 || saved == -1 {
return;
}
let null = match std::fs::OpenOptions::new().write(true).open("NUL") {
Ok(f) => f,
Err(_) => return,
};
let h = null.into_raw_handle() as isize;
unsafe { SetStdHandle(STD_ERROR_HANDLE, h) };
NULL.store(h, Ordering::Relaxed);
SAVED.store(saved, Ordering::Relaxed);
}
pub fn restore() {
let saved = SAVED.swap(0, Ordering::Relaxed);
if saved != 0 {
unsafe { SetStdHandle(STD_ERROR_HANDLE, saved) };
}
let null = NULL.swap(0, Ordering::Relaxed);
if null != 0 {
unsafe { CloseHandle(null) };
}
}
}
#[cfg(not(any(unix, windows)))]
mod imp {
pub fn silence() {}
pub fn restore() {}
}
pub use imp::{restore, silence};