1 //! libc syscalls supporting `rustix::termios`.
2 //!
3 //! # Safety
4 //!
5 //! See the `rustix::backend::syscalls` module documentation for details.
6
7 use super::super::c;
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")))]
12 use crate::ffi::CStr;
13 #[cfg(not(target_os = "wasi"))]
14 use crate::io;
15 #[cfg(not(target_os = "wasi"))]
16 use crate::process::{Pid, RawNonZeroPid};
17 #[cfg(not(target_os = "wasi"))]
18 use crate::termios::{Action, OptionalActions, QueueSelector, Speed, Termios, Winsize};
19 use core::mem::MaybeUninit;
20
21 #[cfg(not(target_os = "wasi"))]
tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios>22 pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
23 let mut result = MaybeUninit::<Termios>::uninit();
24 unsafe {
25 ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr()))?;
26 Ok(result.assume_init())
27 }
28 }
29
30 #[cfg(not(target_os = "wasi"))]
tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid>31 pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
32 unsafe {
33 let pid = ret_pid_t(c::tcgetpgrp(borrowed_fd(fd)))?;
34 debug_assert_ne!(pid, 0);
35 Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
36 }
37 }
38
39 #[cfg(not(target_os = "wasi"))]
tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()>40 pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
41 unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
42 }
43
44 #[cfg(not(target_os = "wasi"))]
tcsetattr( fd: BorrowedFd, optional_actions: OptionalActions, termios: &Termios, ) -> io::Result<()>45 pub(crate) fn tcsetattr(
46 fd: BorrowedFd,
47 optional_actions: OptionalActions,
48 termios: &Termios,
49 ) -> io::Result<()> {
50 unsafe {
51 ret(c::tcsetattr(
52 borrowed_fd(fd),
53 optional_actions as _,
54 termios,
55 ))
56 }
57 }
58
59 #[cfg(not(target_os = "wasi"))]
tcsendbreak(fd: BorrowedFd) -> io::Result<()>60 pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
61 unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
62 }
63
64 #[cfg(not(target_os = "wasi"))]
tcdrain(fd: BorrowedFd) -> io::Result<()>65 pub(crate) fn tcdrain(fd: BorrowedFd) -> io::Result<()> {
66 unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
67 }
68
69 #[cfg(not(target_os = "wasi"))]
tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()>70 pub(crate) fn tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()> {
71 unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
72 }
73
74 #[cfg(not(target_os = "wasi"))]
tcflow(fd: BorrowedFd, action: Action) -> io::Result<()>75 pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> {
76 unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
77 }
78
79 #[cfg(not(target_os = "wasi"))]
tcgetsid(fd: BorrowedFd) -> io::Result<Pid>80 pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result<Pid> {
81 unsafe {
82 let pid = ret_pid_t(c::tcgetsid(borrowed_fd(fd)))?;
83 debug_assert_ne!(pid, 0);
84 Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
85 }
86 }
87
88 #[cfg(not(target_os = "wasi"))]
tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()>89 pub(crate) fn tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()> {
90 unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
91 }
92
93 #[cfg(not(target_os = "wasi"))]
tcgetwinsize(fd: BorrowedFd) -> io::Result<Winsize>94 pub(crate) fn tcgetwinsize(fd: BorrowedFd) -> io::Result<Winsize> {
95 unsafe {
96 let mut buf = MaybeUninit::<Winsize>::uninit();
97 ret(c::ioctl(
98 borrowed_fd(fd),
99 c::TIOCGWINSZ.into(),
100 buf.as_mut_ptr(),
101 ))?;
102 Ok(buf.assume_init())
103 }
104 }
105
106 #[cfg(not(target_os = "wasi"))]
107 #[inline]
108 #[must_use]
cfgetospeed(termios: &Termios) -> Speed109 pub(crate) fn cfgetospeed(termios: &Termios) -> Speed {
110 unsafe { c::cfgetospeed(termios) }
111 }
112
113 #[cfg(not(target_os = "wasi"))]
114 #[inline]
115 #[must_use]
cfgetispeed(termios: &Termios) -> Speed116 pub(crate) fn cfgetispeed(termios: &Termios) -> Speed {
117 unsafe { c::cfgetispeed(termios) }
118 }
119
120 #[cfg(not(target_os = "wasi"))]
121 #[inline]
cfmakeraw(termios: &mut Termios)122 pub(crate) fn cfmakeraw(termios: &mut Termios) {
123 unsafe { c::cfmakeraw(termios) }
124 }
125
126 #[cfg(not(target_os = "wasi"))]
127 #[inline]
cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()>128 pub(crate) fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
129 unsafe { ret(c::cfsetospeed(termios, speed)) }
130 }
131
132 #[cfg(not(target_os = "wasi"))]
133 #[inline]
cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()>134 pub(crate) fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
135 unsafe { ret(c::cfsetispeed(termios, speed)) }
136 }
137
138 #[cfg(not(target_os = "wasi"))]
139 #[inline]
cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()>140 pub(crate) fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
141 unsafe { ret(c::cfsetspeed(termios, speed)) }
142 }
143
isatty(fd: BorrowedFd<'_>) -> bool144 pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
145 // Use the return value of `isatty` alone. We don't check `errno` because
146 // we return `bool` rather than `io::Result<bool>`, because we assume
147 // `BorrrowedFd` protects us from `EBADF`, and any other reasonably
148 // anticipated errno value would end up interpreted as "assume it's not a
149 // terminal" anyway.
150 unsafe { c::isatty(borrowed_fd(fd)) != 0 }
151 }
152
153 #[cfg(feature = "procfs")]
154 #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
ttyname(dirfd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize>155 pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
156 unsafe {
157 // `ttyname_r` returns its error status rather than using `errno`.
158 match c::ttyname_r(borrowed_fd(dirfd), buf.as_mut_ptr().cast(), buf.len()) {
159 0 => Ok(CStr::from_ptr(buf.as_ptr().cast()).to_bytes().len()),
160 err => Err(io::Errno::from_raw_os_error(err)),
161 }
162 }
163 }
164