]> git.proxmox.com Git - rustc.git/blob - vendor/rustix/src/backend/libc/termios/syscalls.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / rustix / src / backend / libc / termios / syscalls.rs
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 use crate::io;
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;
18
19 pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
20 let mut result = MaybeUninit::<Termios>::uninit();
21 unsafe {
22 ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr()))?;
23 Ok(result.assume_init())
24 }
25 }
26
27 pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
28 unsafe {
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)))
32 }
33 }
34
35 pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
36 unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
37 }
38
39 pub(crate) fn tcsetattr(
40 fd: BorrowedFd,
41 optional_actions: OptionalActions,
42 termios: &Termios,
43 ) -> io::Result<()> {
44 unsafe {
45 ret(c::tcsetattr(
46 borrowed_fd(fd),
47 optional_actions as _,
48 termios,
49 ))
50 }
51 }
52
53 pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
54 unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
55 }
56
57 pub(crate) fn tcdrain(fd: BorrowedFd) -> io::Result<()> {
58 unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
59 }
60
61 pub(crate) fn tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()> {
62 unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
63 }
64
65 pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> {
66 unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
67 }
68
69 pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result<Pid> {
70 unsafe {
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)))
74 }
75 }
76
77 pub(crate) fn tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()> {
78 unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
79 }
80
81 pub(crate) fn tcgetwinsize(fd: BorrowedFd) -> io::Result<Winsize> {
82 unsafe {
83 let mut buf = MaybeUninit::<Winsize>::uninit();
84 ret(c::ioctl(
85 borrowed_fd(fd),
86 c::TIOCGWINSZ.into(),
87 buf.as_mut_ptr(),
88 ))?;
89 Ok(buf.assume_init())
90 }
91 }
92
93 #[inline]
94 #[must_use]
95 pub(crate) fn cfgetospeed(termios: &Termios) -> Speed {
96 unsafe { c::cfgetospeed(termios) }
97 }
98
99 #[inline]
100 #[must_use]
101 pub(crate) fn cfgetispeed(termios: &Termios) -> Speed {
102 unsafe { c::cfgetispeed(termios) }
103 }
104
105 #[inline]
106 pub(crate) fn cfmakeraw(termios: &mut Termios) {
107 unsafe { c::cfmakeraw(termios) }
108 }
109
110 #[inline]
111 pub(crate) fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
112 unsafe { ret(c::cfsetospeed(termios, speed)) }
113 }
114
115 #[inline]
116 pub(crate) fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
117 unsafe { ret(c::cfsetispeed(termios, speed)) }
118 }
119
120 #[inline]
121 pub(crate) fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
122 unsafe { ret(c::cfsetspeed(termios, speed)) }
123 }
124
125 pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
126 let res = unsafe { c::isatty(borrowed_fd(fd)) };
127 if res == 0 {
128 match errno().0 {
129 #[cfg(not(any(target_os = "android", target_os = "linux")))]
130 c::ENOTTY => false,
131
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,
136
137 // Darwin mysteriously returns `EOPNOTSUPP` sometimes.
138 #[cfg(any(target_os = "ios", target_os = "macos"))]
139 c::EOPNOTSUPP => false,
140
141 err => panic!("unexpected error from isatty: {:?}", err),
142 }
143 } else {
144 true
145 }
146 }
147
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> {
151 unsafe {
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)),
156 }
157 }
158 }