Skip to content

Commit 8169194

Browse files
authored
Support termios2 (#542)
Signed-off-by: Alex Saveau <[email protected]>
1 parent a596f45 commit 8169194

File tree

6 files changed

+238
-2
lines changed

6 files changed

+238
-2
lines changed

src/backend/libc/termios/syscalls.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,27 @@ pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
2727
}
2828
}
2929

30+
#[cfg(all(
31+
any(target_os = "android", target_os = "linux"),
32+
any(
33+
target_arch = "x86",
34+
target_arch = "x86_64",
35+
target_arch = "x32",
36+
target_arch = "riscv64",
37+
target_arch = "aarch64",
38+
target_arch = "arm",
39+
target_arch = "mips",
40+
target_arch = "mips64",
41+
)
42+
))]
43+
pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result<crate::termios::Termios2> {
44+
let mut result = MaybeUninit::<crate::termios::Termios2>::uninit();
45+
unsafe {
46+
ret(c::ioctl(borrowed_fd(fd), c::TCGETS2, result.as_mut_ptr()))?;
47+
Ok(result.assume_init())
48+
}
49+
}
50+
3051
#[cfg(not(target_os = "wasi"))]
3152
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
3253
unsafe {
@@ -56,6 +77,33 @@ pub(crate) fn tcsetattr(
5677
}
5778
}
5879

80+
#[cfg(all(
81+
any(target_os = "android", target_os = "linux"),
82+
any(
83+
target_arch = "x86",
84+
target_arch = "x86_64",
85+
target_arch = "x32",
86+
target_arch = "riscv64",
87+
target_arch = "aarch64",
88+
target_arch = "arm",
89+
target_arch = "mips",
90+
target_arch = "mips64",
91+
)
92+
))]
93+
pub(crate) fn tcsetattr2(
94+
fd: BorrowedFd,
95+
optional_actions: OptionalActions,
96+
termios: &crate::termios::Termios2,
97+
) -> io::Result<()> {
98+
unsafe {
99+
ret(c::ioctl(
100+
borrowed_fd(fd),
101+
(c::TCSETS2 as u32 + optional_actions as u32) as _,
102+
termios,
103+
))
104+
}
105+
}
106+
59107
#[cfg(not(target_os = "wasi"))]
60108
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
61109
unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }

src/backend/libc/termios/types.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,31 @@ pub enum Action {
5252
IOn = c::TCION,
5353
}
5454

55-
/// `struct termios` for use with [`tcgetattr`].
55+
/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`].
5656
///
5757
/// [`tcgetattr`]: crate::termios::tcgetattr
58+
/// [`tcsetattr`]: crate::termios::tcsetattr
5859
pub type Termios = c::termios;
5960

61+
/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`].
62+
///
63+
/// [`tcgetattr2`]: crate::termios::tcgetattr2
64+
/// [`tcsetattr2`]: crate::termios::tcsetattr2
65+
#[cfg(all(
66+
any(target_os = "android", target_os = "linux"),
67+
any(
68+
target_arch = "x86",
69+
target_arch = "x86_64",
70+
target_arch = "x32",
71+
target_arch = "riscv64",
72+
target_arch = "aarch64",
73+
target_arch = "arm",
74+
target_arch = "mips",
75+
target_arch = "mips64",
76+
)
77+
))]
78+
pub type Termios2 = c::termios2;
79+
6080
/// `struct winsize` for use with [`tcgetwinsize`].
6181
///
6282
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
@@ -824,6 +844,10 @@ pub const B3500000: Speed = c::B3500000;
824844
)))]
825845
pub const B4000000: Speed = c::B4000000;
826846

847+
/// `BOTHER`
848+
#[cfg(any(target_os = "android", target_os = "linux"))]
849+
pub const BOTHER: c::c_uint = c::BOTHER;
850+
827851
/// `CSIZE`
828852
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
829853
pub const CSIZE: c::c_uint = c::CSIZE;

src/backend/linux_raw/termios/syscalls.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,30 @@ pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
4141
}
4242
}
4343

44+
#[inline]
45+
#[cfg(any(
46+
target_arch = "x86",
47+
target_arch = "x86_64",
48+
target_arch = "x32",
49+
target_arch = "riscv64",
50+
target_arch = "aarch64",
51+
target_arch = "arm",
52+
target_arch = "mips",
53+
target_arch = "mips64",
54+
))]
55+
pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result<crate::termios::Termios2> {
56+
unsafe {
57+
let mut result = MaybeUninit::<crate::termios::Termios2>::uninit();
58+
ret(syscall!(
59+
__NR_ioctl,
60+
fd,
61+
c_uint(linux_raw_sys::ioctl::TCGETS2),
62+
&mut result
63+
))?;
64+
Ok(result.assume_init())
65+
}
66+
}
67+
4468
#[inline]
4569
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
4670
unsafe {
@@ -77,6 +101,32 @@ pub(crate) fn tcsetattr(
77101
}
78102
}
79103

104+
#[inline]
105+
#[cfg(any(
106+
target_arch = "x86",
107+
target_arch = "x86_64",
108+
target_arch = "x32",
109+
target_arch = "riscv64",
110+
target_arch = "aarch64",
111+
target_arch = "arm",
112+
target_arch = "mips",
113+
target_arch = "mips64",
114+
))]
115+
pub(crate) fn tcsetattr2(
116+
fd: BorrowedFd,
117+
optional_actions: OptionalActions,
118+
termios: &crate::termios::Termios2,
119+
) -> io::Result<()> {
120+
unsafe {
121+
ret(syscall_readonly!(
122+
__NR_ioctl,
123+
fd,
124+
c_uint(linux_raw_sys::ioctl::TCSETS2 + optional_actions as u32),
125+
by_ref(termios)
126+
))
127+
}
128+
}
129+
80130
#[inline]
81131
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
82132
unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TCSBRK), c_uint(0))) }

src/backend/linux_raw/termios/types.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,28 @@ pub enum Action {
5252
IOn = linux_raw_sys::general::TCION,
5353
}
5454

55-
/// `struct termios` for use with [`tcgetattr`].
55+
/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`].
5656
///
5757
/// [`tcgetattr`]: crate::termios::tcgetattr
58+
/// [`tcsetattr`]: crate::termios::tcsetattr
5859
pub type Termios = linux_raw_sys::general::termios;
5960

61+
/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`].
62+
///
63+
/// [`tcgetattr2`]: crate::termios::tcgetattr2
64+
/// [`tcsetattr2`]: crate::termios::tcsetattr2
65+
#[cfg(any(
66+
target_arch = "x86",
67+
target_arch = "x86_64",
68+
target_arch = "x32",
69+
target_arch = "riscv64",
70+
target_arch = "aarch64",
71+
target_arch = "arm",
72+
target_arch = "mips",
73+
target_arch = "mips64",
74+
))]
75+
pub type Termios2 = linux_raw_sys::general::termios2;
76+
6077
/// `struct winsize` for use with [`tcgetwinsize`].
6178
///
6279
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
@@ -353,6 +370,9 @@ pub const B3500000: Speed = linux_raw_sys::general::B3500000;
353370
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
354371
pub const B4000000: Speed = linux_raw_sys::general::B4000000;
355372

373+
/// `BOTHER`
374+
pub const BOTHER: c::c_uint = linux_raw_sys::general::BOTHER;
375+
356376
/// `CSIZE`
357377
pub const CSIZE: c::c_uint = linux_raw_sys::general::CSIZE;
358378

src/termios/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ pub use tc::{
2222
tcsetpgrp, tcsetwinsize, Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios,
2323
Winsize,
2424
};
25+
#[cfg(all(
26+
any(target_os = "android", target_os = "linux"),
27+
any(
28+
target_arch = "x86",
29+
target_arch = "x86_64",
30+
target_arch = "x32",
31+
target_arch = "riscv64",
32+
target_arch = "aarch64",
33+
target_arch = "arm",
34+
target_arch = "mips",
35+
target_arch = "mips64",
36+
)
37+
))]
38+
pub use tc::{tcgetattr2, tcsetattr2, Termios2};
2539
#[cfg(not(windows))]
2640
pub use tty::isatty;
2741
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]

src/termios/tc.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ use crate::fd::AsFd;
22
use crate::process::Pid;
33
use crate::{backend, io};
44

5+
#[cfg(all(
6+
any(target_os = "android", target_os = "linux"),
7+
any(
8+
target_arch = "x86",
9+
target_arch = "x86_64",
10+
target_arch = "x32",
11+
target_arch = "riscv64",
12+
target_arch = "aarch64",
13+
target_arch = "arm",
14+
target_arch = "mips",
15+
target_arch = "mips64",
16+
)
17+
))]
18+
pub use backend::termios::types::Termios2;
519
pub use backend::termios::types::{
620
Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios, Winsize,
721
};
@@ -25,6 +39,37 @@ pub fn tcgetattr<Fd: AsFd>(fd: Fd) -> io::Result<Termios> {
2539
backend::termios::syscalls::tcgetattr(fd.as_fd())
2640
}
2741

42+
/// `tcgetattr2(fd)`—Get terminal attributes.
43+
///
44+
/// Also known as the `TCGETS2` operation with `ioctl`.
45+
///
46+
/// # References
47+
/// - [POSIX `tcgetattr`]
48+
/// - [Linux `ioctl_tty`]
49+
/// - [Linux `termios`]
50+
///
51+
/// [POSIX `tcgetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html
52+
/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
53+
/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
54+
#[inline]
55+
#[doc(alias = "TCGETS2")]
56+
#[cfg(all(
57+
any(target_os = "android", target_os = "linux"),
58+
any(
59+
target_arch = "x86",
60+
target_arch = "x86_64",
61+
target_arch = "x32",
62+
target_arch = "riscv64",
63+
target_arch = "aarch64",
64+
target_arch = "arm",
65+
target_arch = "mips",
66+
target_arch = "mips64",
67+
)
68+
))]
69+
pub fn tcgetattr2<Fd: AsFd>(fd: Fd) -> io::Result<Termios2> {
70+
backend::termios::syscalls::tcgetattr2(fd.as_fd())
71+
}
72+
2873
/// `tcgetwinsize(fd)`—Get the current terminal window size.
2974
///
3075
/// Also known as the `TIOCGWINSZ` operation with `ioctl`.
@@ -96,6 +141,41 @@ pub fn tcsetattr<Fd: AsFd>(
96141
backend::termios::syscalls::tcsetattr(fd.as_fd(), optional_actions, termios)
97142
}
98143

144+
/// `tcsetattr2(fd)`—Set terminal attributes.
145+
///
146+
/// Also known as the `TCSETS2` operation with `ioctl`.
147+
///
148+
/// # References
149+
/// - [POSIX `tcsetattr`]
150+
/// - [Linux `ioctl_tty`]
151+
/// - [Linux `termios`]
152+
///
153+
/// [POSIX `tcsetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html
154+
/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
155+
/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
156+
#[inline]
157+
#[doc(alias = "TCSETS2")]
158+
#[cfg(all(
159+
any(target_os = "android", target_os = "linux"),
160+
any(
161+
target_arch = "x86",
162+
target_arch = "x86_64",
163+
target_arch = "x32",
164+
target_arch = "riscv64",
165+
target_arch = "aarch64",
166+
target_arch = "arm",
167+
target_arch = "mips",
168+
target_arch = "mips64",
169+
)
170+
))]
171+
pub fn tcsetattr2<Fd: AsFd>(
172+
fd: Fd,
173+
optional_actions: OptionalActions,
174+
termios: &Termios2,
175+
) -> io::Result<()> {
176+
backend::termios::syscalls::tcsetattr2(fd.as_fd(), optional_actions, termios)
177+
}
178+
99179
/// `tcsendbreak(fd, 0)`—Transmit zero-valued bits.
100180
///
101181
/// Also known as the `TCSBRK` operation with `ioctl`, with a duration of 0.

0 commit comments

Comments
 (0)