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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
@@ -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