use nix::sys::termios::{self, SetArg, Termios};
use std::sync::Mutex;
static SAVED: Mutex<Option<Termios>> = Mutex::new(None);
pub(crate) fn enter_raw_mode() {
let fd = libc::STDIN_FILENO;
if unsafe { libc::isatty(fd) } == 0 {
return;
}
let Ok(current) = termios::tcgetattr(unsafe { borrowed(fd) }) else {
return;
};
{
let mut g = SAVED.lock().unwrap();
if g.is_none() {
*g = Some(current.clone());
}
}
let mut raw = current;
termios::cfmakeraw(&mut raw);
let _ = termios::tcsetattr(unsafe { borrowed(fd) }, SetArg::TCSANOW, &raw);
}
pub(crate) fn restore_terminal() {
let saved = match SAVED.try_lock() {
Ok(g) => g.clone(),
Err(_) => return,
};
if let Some(t) = saved {
let fd = libc::STDIN_FILENO;
let _ = termios::tcsetattr(unsafe { borrowed(fd) }, SetArg::TCSANOW, &t);
}
}
pub(crate) fn install_signal_handlers() {
extern "C" fn on_signal(sig: libc::c_int) {
restore_terminal();
unsafe { libc::_exit(128 + sig) }
}
unsafe {
let h = on_signal as *const () as usize;
libc::signal(libc::SIGINT, h);
libc::signal(libc::SIGTERM, h);
libc::signal(libc::SIGHUP, h);
libc::atexit(on_atexit_wrap);
}
}
extern "C" fn on_atexit_wrap() {
restore_terminal();
}
unsafe fn borrowed(fd: libc::c_int) -> std::os::fd::BorrowedFd<'static> {
std::os::fd::BorrowedFd::borrow_raw(fd)
}