pty: update libc functions for ptyd changes
Of note is that `unlockpt` is required, both by the standard, and our implementation. This has been taken care of inside of `openpty`, which is the only non-libc way we are acquiring ptys. Additionally, it has been modified such that it is POSIX compliant, so any outside future changes to ptyd will not affect it. This is part of my ptyd changes (#100). This can be safely merged once the changes from base/ and userutils/ are merged alongside it.
This commit is contained in:
@@ -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
|
||||
|
||||
+26
-13
@@ -1,29 +1,42 @@
|
||||
use crate::{
|
||||
error::ResultExt,
|
||||
header::{fcntl, unistd},
|
||||
platform::{
|
||||
Pal, Sys,
|
||||
types::{c_char, c_int, ssize_t},
|
||||
header::{
|
||||
fcntl,
|
||||
stdlib::{grantpt, posix_openpt, ptsname_r, unlockpt},
|
||||
unistd,
|
||||
},
|
||||
platform::types::{c_char, c_int},
|
||||
};
|
||||
|
||||
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) };
|
||||
let master = unsafe { posix_openpt(fcntl::O_RDWR | fcntl::O_NOCTTY) };
|
||||
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 {
|
||||
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(());
|
||||
}
|
||||
name[count as usize] = 0;
|
||||
|
||||
let slave = unsafe { fcntl::open(name.as_ptr() as *const c_char, fcntl::O_RDWR, 0) };
|
||||
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(());
|
||||
|
||||
+15
-35
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user