Skip to content

Commit

Permalink
Support termios2 (#542)
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX authored Feb 28, 2023
1 parent a596f45 commit 8169194
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 2 deletions.
48 changes: 48 additions & 0 deletions src/backend/libc/termios/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,27 @@ pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
}
}

#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result<crate::termios::Termios2> {
let mut result = MaybeUninit::<crate::termios::Termios2>::uninit();
unsafe {
ret(c::ioctl(borrowed_fd(fd), c::TCGETS2, result.as_mut_ptr()))?;
Ok(result.assume_init())
}
}

#[cfg(not(target_os = "wasi"))]
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
unsafe {
Expand Down Expand Up @@ -56,6 +77,33 @@ pub(crate) fn tcsetattr(
}
}

#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub(crate) fn tcsetattr2(
fd: BorrowedFd,
optional_actions: OptionalActions,
termios: &crate::termios::Termios2,
) -> io::Result<()> {
unsafe {
ret(c::ioctl(
borrowed_fd(fd),
(c::TCSETS2 as u32 + optional_actions as u32) as _,
termios,
))
}
}

#[cfg(not(target_os = "wasi"))]
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
Expand Down
26 changes: 25 additions & 1 deletion src/backend/libc/termios/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,31 @@ pub enum Action {
IOn = c::TCION,
}

/// `struct termios` for use with [`tcgetattr`].
/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`].
///
/// [`tcgetattr`]: crate::termios::tcgetattr
/// [`tcsetattr`]: crate::termios::tcsetattr
pub type Termios = c::termios;

/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`].
///
/// [`tcgetattr2`]: crate::termios::tcgetattr2
/// [`tcsetattr2`]: crate::termios::tcsetattr2
#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub type Termios2 = c::termios2;

/// `struct winsize` for use with [`tcgetwinsize`].
///
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
Expand Down Expand Up @@ -824,6 +844,10 @@ pub const B3500000: Speed = c::B3500000;
)))]
pub const B4000000: Speed = c::B4000000;

/// `BOTHER`
#[cfg(any(target_os = "android", target_os = "linux"))]
pub const BOTHER: c::c_uint = c::BOTHER;

/// `CSIZE`
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
pub const CSIZE: c::c_uint = c::CSIZE;
Expand Down
50 changes: 50 additions & 0 deletions src/backend/linux_raw/termios/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@ pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
}
}

#[inline]
#[cfg(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
))]
pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result<crate::termios::Termios2> {
unsafe {
let mut result = MaybeUninit::<crate::termios::Termios2>::uninit();
ret(syscall!(
__NR_ioctl,
fd,
c_uint(linux_raw_sys::ioctl::TCGETS2),
&mut result
))?;
Ok(result.assume_init())
}
}

#[inline]
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
unsafe {
Expand Down Expand Up @@ -77,6 +101,32 @@ pub(crate) fn tcsetattr(
}
}

#[inline]
#[cfg(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
))]
pub(crate) fn tcsetattr2(
fd: BorrowedFd,
optional_actions: OptionalActions,
termios: &crate::termios::Termios2,
) -> io::Result<()> {
unsafe {
ret(syscall_readonly!(
__NR_ioctl,
fd,
c_uint(linux_raw_sys::ioctl::TCSETS2 + optional_actions as u32),
by_ref(termios)
))
}
}

#[inline]
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TCSBRK), c_uint(0))) }
Expand Down
22 changes: 21 additions & 1 deletion src/backend/linux_raw/termios/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,28 @@ pub enum Action {
IOn = linux_raw_sys::general::TCION,
}

/// `struct termios` for use with [`tcgetattr`].
/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`].
///
/// [`tcgetattr`]: crate::termios::tcgetattr
/// [`tcsetattr`]: crate::termios::tcsetattr
pub type Termios = linux_raw_sys::general::termios;

/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`].
///
/// [`tcgetattr2`]: crate::termios::tcgetattr2
/// [`tcsetattr2`]: crate::termios::tcsetattr2
#[cfg(any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
))]
pub type Termios2 = linux_raw_sys::general::termios2;

/// `struct winsize` for use with [`tcgetwinsize`].
///
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
Expand Down Expand Up @@ -353,6 +370,9 @@ pub const B3500000: Speed = linux_raw_sys::general::B3500000;
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
pub const B4000000: Speed = linux_raw_sys::general::B4000000;

/// `BOTHER`
pub const BOTHER: c::c_uint = linux_raw_sys::general::BOTHER;

/// `CSIZE`
pub const CSIZE: c::c_uint = linux_raw_sys::general::CSIZE;

Expand Down
14 changes: 14 additions & 0 deletions src/termios/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ pub use tc::{
tcsetpgrp, tcsetwinsize, Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios,
Winsize,
};
#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub use tc::{tcgetattr2, tcsetattr2, Termios2};
#[cfg(not(windows))]
pub use tty::isatty;
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
Expand Down
80 changes: 80 additions & 0 deletions src/termios/tc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ use crate::fd::AsFd;
use crate::process::Pid;
use crate::{backend, io};

#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub use backend::termios::types::Termios2;
pub use backend::termios::types::{
Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios, Winsize,
};
Expand All @@ -25,6 +39,37 @@ pub fn tcgetattr<Fd: AsFd>(fd: Fd) -> io::Result<Termios> {
backend::termios::syscalls::tcgetattr(fd.as_fd())
}

/// `tcgetattr2(fd)`—Get terminal attributes.
///
/// Also known as the `TCGETS2` operation with `ioctl`.
///
/// # References
/// - [POSIX `tcgetattr`]
/// - [Linux `ioctl_tty`]
/// - [Linux `termios`]
///
/// [POSIX `tcgetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html
/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
#[inline]
#[doc(alias = "TCGETS2")]
#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub fn tcgetattr2<Fd: AsFd>(fd: Fd) -> io::Result<Termios2> {
backend::termios::syscalls::tcgetattr2(fd.as_fd())
}

/// `tcgetwinsize(fd)`—Get the current terminal window size.
///
/// Also known as the `TIOCGWINSZ` operation with `ioctl`.
Expand Down Expand Up @@ -96,6 +141,41 @@ pub fn tcsetattr<Fd: AsFd>(
backend::termios::syscalls::tcsetattr(fd.as_fd(), optional_actions, termios)
}

/// `tcsetattr2(fd)`—Set terminal attributes.
///
/// Also known as the `TCSETS2` operation with `ioctl`.
///
/// # References
/// - [POSIX `tcsetattr`]
/// - [Linux `ioctl_tty`]
/// - [Linux `termios`]
///
/// [POSIX `tcsetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html
/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html
/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html
#[inline]
#[doc(alias = "TCSETS2")]
#[cfg(all(
any(target_os = "android", target_os = "linux"),
any(
target_arch = "x86",
target_arch = "x86_64",
target_arch = "x32",
target_arch = "riscv64",
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
)
))]
pub fn tcsetattr2<Fd: AsFd>(
fd: Fd,
optional_actions: OptionalActions,
termios: &Termios2,
) -> io::Result<()> {
backend::termios::syscalls::tcsetattr2(fd.as_fd(), optional_actions, termios)
}

/// `tcsendbreak(fd, 0)`—Transmit zero-valued bits.
///
/// Also known as the `TCSBRK` operation with `ioctl`, with a duration of 0.
Expand Down

0 comments on commit 8169194

Please sign in to comment.