From c3c9e3f619f068dfd3feef1a78bc51a0e9d57ea6 Mon Sep 17 00:00:00 2001 From: Josh Megnauth Date: Mon, 11 Aug 2025 02:43:25 -0400 Subject: [PATCH] Add termios constant for VDISABLE _POSIX_VDISABLE is an extension that disables terminal special characters. See: * redox-os/termios!3 * redox-os/base!27 --- src/header/fcntl/linux.rs | 1 + src/header/pty/linux.rs | 6 +-- src/header/termios/linux.rs | 4 ++ src/header/termios/redox.rs | 4 ++ src/header/unistd/pathconf.rs | 5 +- tests/expected/bins_dynamic/termios.stderr | 0 tests/expected/bins_dynamic/termios.stdout | 0 tests/expected/bins_static/termios.stderr | 0 tests/expected/bins_static/termios.stdout | 0 tests/termios.c | 57 ++++++++++++++++++++++ 10 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 tests/expected/bins_dynamic/termios.stderr create mode 100644 tests/expected/bins_dynamic/termios.stdout create mode 100644 tests/expected/bins_static/termios.stderr create mode 100644 tests/expected/bins_static/termios.stdout create mode 100644 tests/termios.c diff --git a/src/header/fcntl/linux.rs b/src/header/fcntl/linux.rs index 39c9233293..0f151a5805 100644 --- a/src/header/fcntl/linux.rs +++ b/src/header/fcntl/linux.rs @@ -6,6 +6,7 @@ pub const O_RDWR: c_int = 0x0002; pub const O_ACCMODE: c_int = 0x0003; pub const O_CREAT: c_int = 0x0040; pub const O_EXCL: c_int = 0x0080; +pub const O_NOCTTY: c_int = 0x0100; pub const O_TRUNC: c_int = 0x0200; pub const O_APPEND: c_int = 0x0400; pub const O_NONBLOCK: c_int = 0x0800; diff --git a/src/header/pty/linux.rs b/src/header/pty/linux.rs index 5b048e21a6..bda6ded3b2 100644 --- a/src/header/pty/linux.rs +++ b/src/header/pty/linux.rs @@ -5,10 +5,8 @@ use crate::{ }; pub(super) unsafe fn openpty(name: &mut [u8]) -> Result<(c_int, c_int), ()> { - const O_NOCTTY: c_int = 0x100; - //TODO: wrap in auto-close struct - let master = fcntl::open(c"/dev/ptmx".as_ptr(), fcntl::O_RDWR | O_NOCTTY, 0); + let master = fcntl::open(c"/dev/ptmx".as_ptr(), fcntl::O_RDWR | fcntl::O_NOCTTY, 0); if master < 0 { return Err(()); } @@ -40,7 +38,7 @@ pub(super) unsafe fn openpty(name: &mut [u8]) -> Result<(c_int, c_int), ()> { let slave = fcntl::open( cursor.get_ref().as_ptr() as *const c_char, - fcntl::O_RDWR | O_NOCTTY, + fcntl::O_RDWR | fcntl::O_NOCTTY, 0, ); if slave < 0 { diff --git a/src/header/termios/linux.rs b/src/header/termios/linux.rs index 1bbfbf3934..2659af5e65 100644 --- a/src/header/termios/linux.rs +++ b/src/header/termios/linux.rs @@ -111,3 +111,7 @@ pub const NOFLSH: usize = 0o000_200; pub const TOSTOP: usize = 0o000_400; pub const IEXTEN: usize = 0o100_000; /* } c_lflag */ + +// POSIX extensions +/// Sentinel value to disable a control char. +pub const _POSIX_VDISABLE: u8 = 0; diff --git a/src/header/termios/redox.rs b/src/header/termios/redox.rs index 2b52146ced..60412d6a54 100644 --- a/src/header/termios/redox.rs +++ b/src/header/termios/redox.rs @@ -104,3 +104,7 @@ pub const NOFLSH: usize = 0x8000_0000; pub const TOSTOP: usize = 0x0040_0000; pub const IEXTEN: usize = 0x0000_0400; /* } c_lflag */ + +// POSIX extensions +/// Sentinel value to disable a control char. +pub const _POSIX_VDISABLE: u8 = 0; diff --git a/src/header/unistd/pathconf.rs b/src/header/unistd/pathconf.rs index 0d81dade9c..d8fe9721dd 100644 --- a/src/header/unistd/pathconf.rs +++ b/src/header/unistd/pathconf.rs @@ -1,5 +1,5 @@ use crate::{ - header::errno, + header::{errno, termios::_POSIX_VDISABLE}, platform::{self, types::*}, }; @@ -11,6 +11,7 @@ pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; +/// Check if file (terminal) supports disabling control chars (CC) pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; @@ -36,7 +37,7 @@ fn pc(name: c_int) -> c_long { _PC_PIPE_BUF => 4096, _PC_CHOWN_RESTRICTED => 1, _PC_NO_TRUNC => 1, - _PC_VDISABLE => 0, + _PC_VDISABLE => _POSIX_VDISABLE.into(), _PC_SYNC_IO => 1, _PC_ASYNC_IO => -1, _PC_PRIO_IO => -1, diff --git a/tests/expected/bins_dynamic/termios.stderr b/tests/expected/bins_dynamic/termios.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_dynamic/termios.stdout b/tests/expected/bins_dynamic/termios.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_static/termios.stderr b/tests/expected/bins_static/termios.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/bins_static/termios.stdout b/tests/expected/bins_static/termios.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/termios.c b/tests/termios.c new file mode 100644 index 0000000000..36436811d6 --- /dev/null +++ b/tests/termios.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include + +int main(void) { + // Check that the tty supports VDISABLE + int vdisable = pathconf("/dev/tty", _PC_VDISABLE); + assert(vdisable == _POSIX_VDISABLE); + + int termfd = open("/dev/tty", O_RDWR, O_NDELAY | O_NOCTTY); + if (termfd < 0) { + perror("open"); + return EXIT_FAILURE; + } + + // Currently set/default options + struct termios termios = {0}; + if (tcgetattr(termfd, &termios) < 0) { + perror("tcgetattr"); + close(termfd); + return EXIT_FAILURE; + } + struct termios term_restore = termios; + + const cc_t verase = termios.c_cc[VERASE]; + assert(verase != _POSIX_VDISABLE); + // Disable backspace key control char + termios.c_cc[VERASE] = _POSIX_VDISABLE; + + if (tcsetattr(termfd, TCSANOW, &termios) < 0) { + perror("tcsetattr (setting VDISABLE)"); + close(termfd); + return EXIT_FAILURE; + } + + // Check that it was actually set + struct termios term_vdisable = {0}; + if (tcgetattr(termfd, &term_vdisable) < 0) { + perror("tcgetattr (after setting VDISABLE)"); + close(termfd); + return EXIT_FAILURE; + } + assert(term_vdisable.c_cc[VERASE] == _POSIX_VDISABLE); + + // Restore old config + if (tcsetattr(termfd, TCSAFLUSH, &term_restore) < 0) { + perror("tcsetattr (restoring settings)"); + close(termfd); + return EXIT_FAILURE; + } + + close(termfd); + return EXIT_SUCCESS; +}