Merge branch 'ptyd-changes' into 'master'

pty: update libc functions for ptyd changes

See merge request redox-os/relibc!1409
This commit is contained in:
Jeremy Soller
2026-06-03 19:24:58 -06:00
8 changed files with 67 additions and 137 deletions
+1
View File
@@ -130,3 +130,4 @@ pub const PTHREAD_DESTRUCTOR_ITERATIONS: c_long = _POSIX_THREAD_DESTRUCTOR_ITERA
pub const PTHREAD_KEYS_MAX: c_long = 4096 * 32;
pub const PTHREAD_STACK_MIN: c_long = 65536;
pub const SYMLOOP_MAX: c_long = 64;
pub const TTY_NAME_MAX: c_long = 32; // "/scheme/pty/".len() + size of usize::MAX as string + 1
-58
View File
@@ -1,58 +0,0 @@
use core::ptr;
use crate::{
header::{fcntl, sys_ioctl, unistd},
io::{Cursor, Write},
platform::types::{c_char, c_int, c_void},
};
pub(super) unsafe fn openpty(name: &mut [u8]) -> Result<(c_int, c_int), ()> {
//TODO: wrap in auto-close struct
let master = unsafe { fcntl::open(c"/dev/ptmx".as_ptr(), fcntl::O_RDWR | fcntl::O_NOCTTY, 0) };
if master < 0 {
return Err(());
}
let mut lock: c_int = 0;
if unsafe {
sys_ioctl::ioctl(
master,
sys_ioctl::TIOCSPTLCK,
ptr::from_mut::<c_int>(&mut lock).cast::<c_void>(),
)
} != 0
{
unistd::close(master);
return Err(());
}
let mut ptn: c_int = 0;
if unsafe {
sys_ioctl::ioctl(
master,
sys_ioctl::TIOCGPTN,
ptr::from_mut::<c_int>(&mut ptn).cast::<c_void>(),
)
} != 0
{
unistd::close(master);
return Err(());
}
let mut cursor = Cursor::new(name);
if let Ok(()) = write!(cursor, "/dev/pts/{}\0", ptn) {}; // TODO handle error
let slave = unsafe {
fcntl::open(
cursor.get_ref().as_ptr().cast::<c_char>(),
fcntl::O_RDWR | fcntl::O_NOCTTY,
0,
)
};
if slave < 0 {
unistd::close(master);
return Err(());
}
Ok((master, slave))
}
+41 -8
View File
@@ -6,7 +6,9 @@ use core::{mem, ptr, slice};
use crate::{
header::{
bits_sigset_t, fcntl, limits, pthread, signal, sys_ioctl, sys_wait, termios, unistd, utmp,
bits_sigset_t, fcntl, limits, pthread, signal,
stdlib::{grantpt, posix_openpt, ptsname_r, unlockpt},
sys_ioctl, sys_wait, termios, unistd, utmp,
},
platform::{
self,
@@ -14,13 +16,44 @@ use crate::{
},
};
#[cfg(target_os = "linux")]
#[path = "linux.rs"]
mod imp;
unsafe fn openpty_inner(name: &mut [u8]) -> Result<(c_int, c_int), ()> {
// TODO: wrap in auto-close struct
let master = unsafe { posix_openpt(fcntl::O_RDWR | fcntl::O_NOCTTY) };
if master < 0 {
return Err(());
}
#[cfg(target_os = "redox")]
#[path = "redox.rs"]
mod imp;
let ret = grantpt(master);
if ret == -1 {
unistd::close(master);
return Err(());
}
let ret = unsafe { unlockpt(master) };
if ret == -1 {
unistd::close(master);
return Err(());
}
let ret = unsafe { ptsname_r(master, name.as_mut_ptr().cast(), name.len()) };
if ret < 0 {
unistd::close(master);
return Err(());
}
let slave = unsafe {
fcntl::open(
name.as_ptr() as *const c_char,
fcntl::O_RDWR | fcntl::O_NOCTTY,
0,
)
};
if slave < 0 {
unistd::close(master);
return Err(());
}
Ok((master, slave))
}
/// See <https://www.man7.org/linux/man-pages/man3/openpty.3.html>.
#[unsafe(no_mangle)]
@@ -38,7 +71,7 @@ pub unsafe extern "C" fn openpty(
&mut tmp_name
};
let (master, slave) = match unsafe { imp::openpty(name) } {
let (master, slave) = match unsafe { openpty_inner(name) } {
Ok(ok) => ok,
Err(()) => return -1,
};
-33
View File
@@ -1,33 +0,0 @@
use crate::{
error::ResultExt,
header::{fcntl, unistd},
platform::{
Pal, Sys,
types::{c_char, c_int, ssize_t},
},
};
pub(super) unsafe fn openpty(name: &mut [u8]) -> Result<(c_int, c_int), ()> {
let master = unsafe { fcntl::open(c"/scheme/pty".as_ptr(), fcntl::O_RDWR, 0) };
if master < 0 {
return Err(());
}
// TODO: better error handling
let count = Sys::fpath(master, name)
.map(|u| u as ssize_t)
.or_minus_one_errno();
if count < 0 {
unistd::close(master);
return Err(());
}
name[count as usize] = 0;
let slave = unsafe { fcntl::open(name.as_ptr() as *const c_char, fcntl::O_RDWR, 0) };
if slave < 0 {
unistd::close(master);
return Err(());
}
Ok((master, slave))
}
+15 -35
View File
@@ -924,8 +924,7 @@ pub unsafe extern "C" fn posix_memalign(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_openpt(flags: c_int) -> c_int {
#[cfg(target_os = "redox")]
let r = unsafe { open(c"/scheme/pty".as_ptr(), flags) };
let r = unsafe { open(c"/scheme/pty/ptmx".as_ptr(), flags) };
#[cfg(target_os = "linux")]
let r = unsafe { open(c"/dev/ptmx".as_ptr(), flags) };
@@ -939,9 +938,11 @@ pub unsafe extern "C" fn posix_openpt(flags: c_int) -> c_int {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/ptsname.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ptsname(fd: c_int) -> *mut c_char {
const PTS_BUFFER_LEN: usize = 9 + mem::size_of::<c_int>() * 3 + 1;
const PTS_BUFFER_LEN: usize = limits::TTY_NAME_MAX as usize;
static mut PTS_BUFFER: [c_char; PTS_BUFFER_LEN] = [0; PTS_BUFFER_LEN];
if unsafe { ptsname_r(fd, (&raw mut PTS_BUFFER).cast(), PTS_BUFFER_LEN) } != 0 {
let ret = unsafe { ptsname_r(fd, (&raw mut PTS_BUFFER).cast(), PTS_BUFFER_LEN) };
if ret != 0 {
platform::ERRNO.set(ret);
ptr::null_mut()
} else {
(&raw mut PTS_BUFFER).cast()
@@ -959,49 +960,28 @@ pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t)
}
}
#[cfg(target_os = "redox")]
// ptsname_r is not allowed to set errno, but it has it as a return value.
#[inline(always)]
unsafe fn __ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
let tty_ptr = unsafe { unistd::ttyname(fd) };
if !tty_ptr.is_null() {
if let Ok(name) = unsafe { CStr::from_ptr(tty_ptr) }.to_str() {
let len = name.len();
if len > buflen {
platform::ERRNO.set(ERANGE);
return ERANGE;
} else {
// we have checked the string will fit in the buffer
// so can use strcpy safely
let s = name.as_ptr().cast();
unsafe {
ptr::copy_nonoverlapping(s, buf, len);
}
return 0;
}
}
}
platform::ERRNO.get()
}
#[cfg(target_os = "linux")]
#[inline(always)]
unsafe fn __ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
let mut pty = 0;
let err = platform::ERRNO.get();
let mut pty: c_int = 0;
if unsafe { ioctl(fd, TIOCGPTN, ptr::from_mut(&mut pty).cast::<c_void>()) } == 0 {
// Linux and Redox use different resource names for PTS's.
#[cfg(target_os = "linux")]
let name = format!("/dev/pts/{}", pty);
#[cfg(target_os = "redox")]
let name = format!("/scheme/pty/{}", pty);
let len = name.len();
if len > buflen {
platform::ERRNO.set(ERANGE);
// We need + 1 to account for the NUL terminator.
if len + 1 > buflen {
ERANGE
} else {
// we have checked the string will fit in the buffer
// so can use strcpy safely
let s = name.as_ptr().cast();
unsafe { ptr::copy_nonoverlapping(s, buf, len) };
platform::ERRNO.set(err);
// NUL-terminate the result.
unsafe { *(buf.add(len + 1)) = 0 };
0
}
} else {
+2
View File
@@ -55,5 +55,7 @@ pub const TIOCSPTLCK: c_ulong = 0x4004_5431;
/// location pointed to by `lock`.
pub const TIOCGPTLCK: c_ulong = 0x8004_5439;
// Get the name of the PT as a c_int.
pub const TIOCGPTN: c_ulong = 0x8004_5430;
/// POSIX `sockatmark()` from `sys/socket.h` is intended to replace this.
pub const SIOCATMARK: c_ulong = 0x8905;
-1
View File
@@ -28,7 +28,6 @@ pub const TIOCSBRK: c_ulong = 0x5427;
pub const TIOCCBRK: c_ulong = 0x5428;
pub const TIOCGRS485: c_ulong = 0x542E;
pub const TIOCSRS485: c_ulong = 0x542F;
pub const TIOCGPTN: c_ulong = 0x8004_5430;
pub const TIOCGDEV: c_ulong = 0x8004_5432;
pub const TCGETX: c_ulong = 0x5432;
pub const TCSETX: c_ulong = 0x5433;
+8 -2
View File
@@ -123,10 +123,16 @@ pub unsafe fn ioctl_inner(fd: c_int, request: c_ulong, out: *mut c_void) -> Resu
dup_write(fd, "winsize", winsize)?;
}
TIOCGPTLCK => {
todo_skip!(0, "ioctl TIOCGPTLCK");
let lock = unsafe { &mut *(out as *mut c_int) };
dup_read(fd, "ptlock", lock)?;
}
TIOCSPTLCK => {
todo_skip!(0, "ioctl TIOCSPTLCK");
let lock = unsafe { &*(out as *const c_int) };
dup_write(fd, "ptlock", lock)?;
}
TIOCGPTN => {
let name = unsafe { &mut *(out as *mut c_int) };
dup_read(fd, "ptsname", name)?;
}
TCSBRK => {
todo_skip!(0, "ioctl TCSBRK");