#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
use crate::c_uint;
#[cfg(all(feature = "unsafe_syscall", not(miri)))]
use crate::{
LINUX_ERRNO, LINUX_FILENO, LINUX_IOCTL, LINUX_TERMIOS_LFLAG, Linux, LinuxError,
LinuxResult as Result, TermSize, is,
};
#[doc = crate::_tags!(linux term)]
#[doc = crate::_doc_location!("sys/os/linux")]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct LinuxTermios {
pub c_iflag: c_uint,
pub c_oflag: c_uint,
pub c_cflag: c_uint,
pub c_lflag: c_uint,
pub c_line: u8,
pub c_cc: [u8; 19],
}
#[cfg_attr(nightly_doc, doc(cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))))]
#[cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))]
unsafe impl crate::_dep::bytemuck::NoUninit for LinuxTermios {}
impl LinuxTermios {
#[must_use]
pub const fn new() -> Self {
Self {
c_iflag: 0,
c_oflag: 0,
c_cflag: 0,
c_lflag: 0,
c_line: 0,
c_cc: [0; 19],
}
}
#[must_use]
pub const fn as_bytes_ptr(&self) -> *const u8 {
self as *const Self as *const u8
}
#[must_use]
pub fn as_mut_bytes_ptr(&mut self) -> *mut u8 {
self as *mut Self as *mut u8
}
}
#[cfg(all(any_target_arch_linux, feature = "unsafe_syscall", not(miri)))]
impl LinuxTermios {
pub fn get_state() -> Result<LinuxTermios> {
let mut state = LinuxTermios::new();
let res = unsafe {
Linux::sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCGETS, state.as_mut_bytes_ptr())
};
is![res >= 0, Ok(state), Err(LinuxError::Sys(res))]
}
pub fn set_state(mut state: LinuxTermios) -> Result<()> {
let res = unsafe {
Linux::sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCSETS, state.as_mut_bytes_ptr())
};
is![res >= 0, Ok(()), Err(LinuxError::Sys(res))]
}
#[must_use]
pub fn is_terminal() -> bool {
match Self::get_state() {
Ok(_) => true,
Err(LinuxError::Sys(err)) => err != -LINUX_ERRNO::ENOTTY && err != -LINUX_ERRNO::EINVAL,
Err(_) => false, }
}
pub fn disable_raw_mode() -> Result<()> {
let mut state = LinuxTermios::get_state()?;
state.c_lflag |= LINUX_TERMIOS_LFLAG::ICANON;
state.c_lflag |= LINUX_TERMIOS_LFLAG::ECHO;
LinuxTermios::set_state(state)
}
pub fn enable_raw_mode() -> Result<()> {
let mut state = Self::get_state()?;
state.c_lflag &= !LINUX_TERMIOS_LFLAG::ICANON;
state.c_lflag &= !LINUX_TERMIOS_LFLAG::ECHO;
LinuxTermios::set_state(state)
}
pub fn get_winsize() -> Result<TermSize> {
let mut winsize = TermSize::default();
let res = unsafe {
Linux::sys_ioctl(
LINUX_FILENO::STDIN,
LINUX_IOCTL::TIOCGWINSZ,
&mut winsize as *mut TermSize as *mut u8,
)
};
is![res >= 0, Ok(winsize), Err(LinuxError::Sys(res))]
}
}