devela/sys/os/linux/structs/
termios.rs1#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
7
8#[cfg(all(feature = "unsafe_syscall", not(miri)))]
9use crate::{
10 LINUX_ERRNO, LINUX_FILENO, LINUX_IOCTL, LINUX_TERMIOS_LFLAG, Linux, LinuxError,
11 LinuxResult as Result, is,
12};
13use crate::{TermSize, c_uint};
14
15#[derive(Clone, Copy, Debug, Default, PartialEq)]
23#[repr(C)]
24pub struct LinuxTermios {
25 pub c_iflag: c_uint,
27
28 pub c_oflag: c_uint,
30
31 pub c_cflag: c_uint,
33
34 pub c_lflag: c_uint,
36
37 pub c_line: u8,
39
40 pub c_cc: [u8; 19],
42}
43
44#[cfg_attr(nightly_doc, doc(cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))))]
45#[cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))]
46unsafe impl crate::_dep::bytemuck::NoUninit for LinuxTermios {}
47
48impl LinuxTermios {
49 #[must_use]
51 pub const fn new() -> Self {
52 Self {
53 c_iflag: 0,
54 c_oflag: 0,
55 c_cflag: 0,
56 c_lflag: 0,
57 c_line: 0,
58 c_cc: [0; 19],
59 }
60 }
61
62 #[must_use]
64 pub const fn as_bytes_ptr(&self) -> *const u8 {
65 self as *const Self as *const u8
66 }
67
68 #[must_use]
70 pub fn as_mut_bytes_ptr(&mut self) -> *mut u8 {
71 self as *mut Self as *mut u8
72 }
73}
74
75#[cfg(all(
76 any(
77 target_arch = "x86_64",
78 target_arch = "x86",
79 target_arch = "arm",
80 target_arch = "aarch64",
81 target_arch = "riscv32",
82 target_arch = "riscv64"
83 ),
84 feature = "unsafe_syscall",
85 not(miri),
86))]
87impl LinuxTermios {
88 pub fn get_state() -> Result<LinuxTermios> {
90 let mut state = LinuxTermios::new();
91 let res = unsafe {
92 Linux::sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCGETS, state.as_mut_bytes_ptr())
93 };
94 is![res >= 0; Ok(state); Err(LinuxError::Sys(res))]
95 }
96
97 pub fn set_state(mut state: LinuxTermios) -> Result<()> {
99 let res = unsafe {
100 Linux::sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCSETS, state.as_mut_bytes_ptr())
101 };
102 is![res >= 0; Ok(()); Err(LinuxError::Sys(res))]
103 }
104
105 #[must_use]
107 pub fn is_terminal() -> bool {
108 match Self::get_state() {
109 Ok(_) => true,
110 Err(LinuxError::Sys(err)) => err != -LINUX_ERRNO::ENOTTY && err != -LINUX_ERRNO::EINVAL,
111 Err(_) => false, }
113 }
114
115 pub fn disable_raw_mode() -> Result<()> {
117 let mut state = LinuxTermios::get_state()?;
118 state.c_lflag |= LINUX_TERMIOS_LFLAG::ICANON;
119 state.c_lflag |= LINUX_TERMIOS_LFLAG::ECHO;
120 LinuxTermios::set_state(state)
121 }
122
123 pub fn enable_raw_mode() -> Result<()> {
125 let mut state = Self::get_state()?;
126 state.c_lflag &= !LINUX_TERMIOS_LFLAG::ICANON;
127 state.c_lflag &= !LINUX_TERMIOS_LFLAG::ECHO;
128 LinuxTermios::set_state(state)
129 }
130
131 pub fn get_winsize() -> Result<TermSize> {
133 let mut winsize = TermSize::default();
134 let res = unsafe {
135 Linux::sys_ioctl(
136 LINUX_FILENO::STDIN,
137 LINUX_IOCTL::TIOCGWINSZ,
138 &mut winsize as *mut TermSize as *mut u8,
139 )
140 };
141 is![res >= 0; Ok(winsize); Err(LinuxError::Sys(res))]
142 }
143}