rustix/backend/libc/pty/
syscalls.rs1use crate::backend::c;
4use crate::backend::conv::{borrowed_fd, ret};
5use crate::fd::BorrowedFd;
6use crate::io;
7#[cfg(all(
8 feature = "alloc",
9 any(
10 apple,
11 linux_like,
12 target_os = "freebsd",
13 target_os = "fuchsia",
14 target_os = "illumos"
15 )
16))]
17use {
18 crate::ffi::{CStr, CString},
19 crate::path::SMALL_PATH_BUFFER_SIZE,
20 alloc::borrow::ToOwned,
21 alloc::vec::Vec,
22};
23
24#[cfg(not(linux_kernel))]
25use crate::{backend::conv::ret_owned_fd, fd::OwnedFd, pty::OpenptFlags};
26
27#[cfg(not(linux_kernel))]
28#[inline]
29pub(crate) fn openpt(flags: OpenptFlags) -> io::Result<OwnedFd> {
30 unsafe { ret_owned_fd(c::posix_openpt(flags.bits() as _)) }
31}
32
33#[cfg(all(
34 feature = "alloc",
35 any(
36 apple,
37 linux_like,
38 target_os = "freebsd",
39 target_os = "fuchsia",
40 target_os = "illumos"
41 )
42))]
43#[inline]
44pub(crate) fn ptsname(fd: BorrowedFd<'_>, mut buffer: Vec<u8>) -> io::Result<CString> {
45 buffer.clear();
48 buffer.reserve(SMALL_PATH_BUFFER_SIZE);
49 buffer.resize(buffer.capacity(), 0_u8);
50
51 loop {
52 #[cfg(any(linux_like, target_os = "fuchsia", target_os = "illumos"))]
54 let r = unsafe { c::ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) };
55
56 #[cfg(target_os = "freebsd")]
58 let r = unsafe {
59 weak! {
60 fn ptsname_r(
61 c::c_int,
62 *mut c::c_char,
63 c::size_t
64 ) -> c::c_int
65 }
66 if let Some(func) = ptsname_r.get() {
67 func(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len())
68 } else {
69 libc::ENOSYS
70 }
71 };
72
73 #[cfg(apple)]
76 let r = unsafe {
77 weak! { fn ptsname_r(c::c_int, *mut c::c_char, c::size_t) -> c::c_int }
78
79 if let Some(libc_ptsname_r) = ptsname_r.get() {
80 libc_ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len())
81 } else {
82 let mut name: [u8; 128] = [0_u8; 128];
85 match c::ioctl(borrowed_fd(fd), c::TIOCPTYGNAME as _, &mut name) {
86 0 => {
87 let len = CStr::from_ptr(name.as_ptr().cast()).to_bytes().len();
88 std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), len + 1);
89 0
90 }
91 _ => libc_errno::errno().0,
92 }
93 }
94 };
95
96 if r == 0 {
97 return Ok(unsafe { CStr::from_ptr(buffer.as_ptr().cast()).to_owned() });
98 }
99 if r != c::ERANGE {
100 return Err(io::Errno::from_raw_os_error(r));
101 }
102
103 buffer.reserve(1);
105 buffer.resize(buffer.capacity(), 0_u8);
106 }
107}
108
109#[inline]
110pub(crate) fn unlockpt(fd: BorrowedFd<'_>) -> io::Result<()> {
111 unsafe { ret(c::unlockpt(borrowed_fd(fd))) }
112}
113
114#[cfg(not(linux_kernel))]
115#[inline]
116pub(crate) fn grantpt(fd: BorrowedFd<'_>) -> io::Result<()> {
117 unsafe { ret(c::grantpt(borrowed_fd(fd))) }
118}