1 //! libc syscalls supporting `rustix::termios`.
5 //! See the `rustix::backend::syscalls` module documentation for details.
8 use super::super::conv
::{borrowed_fd, ret, ret_pid_t}
;
9 use crate::fd
::BorrowedFd
;
10 #[cfg(feature = "procfs")]
11 #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
14 use crate::process
::{Pid, RawNonZeroPid}
;
15 use crate::termios
::{Action, OptionalActions, QueueSelector, Speed, Termios, Winsize}
;
16 use core
::mem
::MaybeUninit
;
17 use libc_errno
::errno
;
19 pub(crate) fn tcgetattr(fd
: BorrowedFd
<'_
>) -> io
::Result
<Termios
> {
20 let mut result
= MaybeUninit
::<Termios
>::uninit();
22 ret(c
::tcgetattr(borrowed_fd(fd
), result
.as_mut_ptr()))?
;
23 Ok(result
.assume_init())
27 pub(crate) fn tcgetpgrp(fd
: BorrowedFd
<'_
>) -> io
::Result
<Pid
> {
29 let pid
= ret_pid_t(c
::tcgetpgrp(borrowed_fd(fd
)))?
;
30 debug_assert_ne
!(pid
, 0);
31 Ok(Pid
::from_raw_nonzero(RawNonZeroPid
::new_unchecked(pid
)))
35 pub(crate) fn tcsetpgrp(fd
: BorrowedFd
<'_
>, pid
: Pid
) -> io
::Result
<()> {
36 unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
39 pub(crate) fn tcsetattr(
41 optional_actions
: OptionalActions
,
47 optional_actions
as _
,
53 pub(crate) fn tcsendbreak(fd
: BorrowedFd
) -> io
::Result
<()> {
54 unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
57 pub(crate) fn tcdrain(fd
: BorrowedFd
) -> io
::Result
<()> {
58 unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
61 pub(crate) fn tcflush(fd
: BorrowedFd
, queue_selector
: QueueSelector
) -> io
::Result
<()> {
62 unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
65 pub(crate) fn tcflow(fd
: BorrowedFd
, action
: Action
) -> io
::Result
<()> {
66 unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
69 pub(crate) fn tcgetsid(fd
: BorrowedFd
) -> io
::Result
<Pid
> {
71 let pid
= ret_pid_t(c
::tcgetsid(borrowed_fd(fd
)))?
;
72 debug_assert_ne
!(pid
, 0);
73 Ok(Pid
::from_raw_nonzero(RawNonZeroPid
::new_unchecked(pid
)))
77 pub(crate) fn tcsetwinsize(fd
: BorrowedFd
, winsize
: Winsize
) -> io
::Result
<()> {
78 unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
81 pub(crate) fn tcgetwinsize(fd
: BorrowedFd
) -> io
::Result
<Winsize
> {
83 let mut buf
= MaybeUninit
::<Winsize
>::uninit();
95 pub(crate) fn cfgetospeed(termios
: &Termios
) -> Speed
{
96 unsafe { c::cfgetospeed(termios) }
101 pub(crate) fn cfgetispeed(termios
: &Termios
) -> Speed
{
102 unsafe { c::cfgetispeed(termios) }
106 pub(crate) fn cfmakeraw(termios
: &mut Termios
) {
107 unsafe { c::cfmakeraw(termios) }
111 pub(crate) fn cfsetospeed(termios
: &mut Termios
, speed
: Speed
) -> io
::Result
<()> {
112 unsafe { ret(c::cfsetospeed(termios, speed)) }
116 pub(crate) fn cfsetispeed(termios
: &mut Termios
, speed
: Speed
) -> io
::Result
<()> {
117 unsafe { ret(c::cfsetispeed(termios, speed)) }
121 pub(crate) fn cfsetspeed(termios
: &mut Termios
, speed
: Speed
) -> io
::Result
<()> {
122 unsafe { ret(c::cfsetspeed(termios, speed)) }
125 pub(crate) fn isatty(fd
: BorrowedFd
<'_
>) -> bool
{
126 let res
= unsafe { c::isatty(borrowed_fd(fd)) }
;
129 #[cfg(not(any(target_os = "android", target_os = "linux")))]
132 // Old Linux versions reportedly return `EINVAL`.
133 // <https://man7.org/linux/man-pages/man3/isatty.3.html#ERRORS>
134 #[cfg(any(target_os = "android", target_os = "linux"))]
135 c
::ENOTTY
| c
::EINVAL
=> false,
137 // Darwin mysteriously returns `EOPNOTSUPP` sometimes.
138 #[cfg(any(target_os = "ios", target_os = "macos"))]
139 c
::EOPNOTSUPP
=> false,
141 err
=> panic
!("unexpected error from isatty: {:?}", err
),
148 #[cfg(feature = "procfs")]
149 #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
150 pub(crate) fn ttyname(dirfd
: BorrowedFd
<'_
>, buf
: &mut [u8]) -> io
::Result
<usize> {
152 // `ttyname_r` returns its error status rather than using `errno`.
153 match c
::ttyname_r(borrowed_fd(dirfd
), buf
.as_mut_ptr().cast(), buf
.len()) {
154 0 => Ok(CStr
::from_ptr(buf
.as_ptr().cast()).to_bytes().len()),
155 err
=> Err(io
::Errno
::from_raw_os_error(err
)),