From eb48b04b545a8ca5d519b2391a0162dc56b64d5e Mon Sep 17 00:00:00 2001 From: Wildan M Date: Fri, 10 Jul 2026 11:22:55 +0700 Subject: [PATCH] redoxerd: Proper pty init --- Cargo.lock | 1 + drivers/redoxerd/Cargo.toml | 1 + drivers/redoxerd/src/main.rs | 61 ++++++++++++++++++++++-------------- ptyd/src/controlterm.rs | 6 +++- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46d637c1bf..5ced8a8f50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1931,6 +1931,7 @@ version = "0.1.0" dependencies = [ "anyhow", "common", + "libc", "libredox", "qemu-exit", "redox_event", diff --git a/drivers/redoxerd/Cargo.toml b/drivers/redoxerd/Cargo.toml index 6214b45a6f..a0fdf65786 100644 --- a/drivers/redoxerd/Cargo.toml +++ b/drivers/redoxerd/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] anyhow.workspace = true +libc.workspace = true libredox.workspace = true redox_event.workspace = true redox_syscall.workspace = true diff --git a/drivers/redoxerd/src/main.rs b/drivers/redoxerd/src/main.rs index 4551ea2e5d..4541496427 100644 --- a/drivers/redoxerd/src/main.rs +++ b/drivers/redoxerd/src/main.rs @@ -1,4 +1,5 @@ use anyhow::Context; +use std::ffi::CStr; use std::fs::{self, OpenOptions}; use std::io; use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; @@ -6,8 +7,8 @@ use std::process::{Child, Command, ExitStatus, Stdio}; mod sys; -const DEFAULT_COLS: u32 = 80; -const DEFAULT_LINES: u32 = 30; +const DEFAULT_COLS: u16 = 80; +const DEFAULT_LINES: u16 = 30; event::user_data! { enum EventData { @@ -80,29 +81,33 @@ fn handle( process.wait() } -fn getpty(columns: u32, lines: u32) -> io::Result<(RawFd, String)> { - let master = libredox::call::open( +/// getpty, copied from getty +pub fn getpty(columns: u16, lines: u16) -> anyhow::Result<(RawFd, String)> { + use libredox::{call as redox, flag}; + let master = redox::open( "/scheme/pty/ptmx", - libredox::flag::O_CLOEXEC - | libredox::flag::O_RDWR - | libredox::flag::O_CREAT - | libredox::flag::O_NONBLOCK, + flag::O_CLOEXEC | flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, 0, - )?; + ) + .context("failed to create PTY")?; - if let Ok(winsize_fd) = libredox::call::dup(master, b"winsize") { - let _ = libredox::call::write( + if let Ok(winsize_fd) = redox::dup(master, b"winsize") { + redox::write( winsize_fd, &redox_termios::Winsize { - ws_row: lines as u16, - ws_col: columns as u16, + ws_row: lines, + ws_col: columns, }, - ); - let _ = libredox::call::close(winsize_fd); + ) + .context("failed to get PTY winsize")?; + let _ = redox::close(winsize_fd); } + let _ = unsafe { libc::grantpt(master as RawFd) }; + let _ = unsafe { libc::unlockpt(master as RawFd) }; - let mut buf: [u8; 4096] = [0; 4096]; - let count = libredox::call::fpath(master, &mut buf)?; + let name = unsafe { libc::ptsname(master as RawFd) }; + let count = unsafe { libc::strlen(name) }; + let buf = unsafe { &*std::ptr::slice_from_raw_parts(name.cast(), count) }; Ok((master as RawFd, unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) })) @@ -115,13 +120,14 @@ fn inner() -> anyhow::Result<()> { let mut config_lines = config.lines(); let (columns, lines) = (DEFAULT_COLS, DEFAULT_LINES); - let (master_fd, pty) = getpty(columns, lines)?; + let (master_fd, pty) = getpty(columns, lines).context("failed to get pty")?; let timeout_fd = libredox::call::open( "/scheme/time/4", libredox::flag::O_CLOEXEC | libredox::flag::O_RDWR | libredox::flag::O_NONBLOCK, 0, - )? as RawFd; + ) + .context("failed to get time")? as RawFd; let event_queue = event::EventQueue::new()?; event_queue.subscribe(master_fd as usize, EventData::Pty, event::EventFlags::READ)?; @@ -131,9 +137,18 @@ fn inner() -> anyhow::Result<()> { event::EventFlags::READ, )?; - let slave_stdin = OpenOptions::new().read(true).open(&pty)?; - let slave_stdout = OpenOptions::new().write(true).open(&pty)?; - let slave_stderr = OpenOptions::new().write(true).open(&pty)?; + let slave_stdin = OpenOptions::new() + .read(true) + .open(&pty) + .context("failed to get pty stdin")?; + let slave_stdout = OpenOptions::new() + .write(true) + .open(&pty) + .context("failed to get pty stdout")?; + let slave_stderr = OpenOptions::new() + .write(true) + .open(&pty) + .context("failed to get pty stderr")?; let Some(name) = config_lines.next() else { anyhow::bail!("/etc/redoxerd does not specify command"); @@ -172,7 +187,7 @@ fn main() { sys::exit_success(); } Err(err) => { - eprintln!("redoxerd: {:#}", err); + eprintln!("redoxerd: {}", err); // Wait a bit for the error message to get flushed through the tty subsystem before exiting. std::thread::sleep(std::time::Duration::from_millis(100)); diff --git a/ptyd/src/controlterm.rs b/ptyd/src/controlterm.rs index 2edef9553b..c0e7908890 100644 --- a/ptyd/src/controlterm.rs +++ b/ptyd/src/controlterm.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::rc::{Rc, Weak}; +use scheme_utils::FpathWriter; use syscall::error::{Error, Result, EAGAIN, EINVAL, EWOULDBLOCK}; use syscall::flag::{EventFlags, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK}; @@ -37,7 +38,10 @@ impl Resource for PtyControlTerm { } fn path(&mut self, buf: &mut [u8]) -> Result { - self.pty.borrow_mut().path(buf) + FpathWriter::with(buf, "pty", |w| { + write!(w, "ptmx").unwrap(); + Ok(()) + }) } fn read(&mut self, buf: &mut [u8]) -> Result {