From 681d8327f59492aa35139e8db4b670cd2aec4e47 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 30 Jul 2024 11:10:43 +0300 Subject: [PATCH] LibC/Kernel: Cleanup termios code This is still not correct, but much better than it used to be --- kernel/include/kernel/Process.h | 4 +- kernel/include/kernel/Terminal/TTY.h | 19 ++++-- kernel/include/kernel/Terminal/VirtualTTY.h | 1 - kernel/include/kernel/Terminal/termios.h | 12 ---- kernel/kernel/Process.cpp | 31 +++++---- kernel/kernel/Terminal/TTY.cpp | 8 +-- .../libraries/LibC/include/sys/syscall.h | 4 +- userspace/libraries/LibC/include/termios.h | 2 + userspace/libraries/LibC/termios.cpp | 67 ++++++++++++++++--- 9 files changed, 99 insertions(+), 49 deletions(-) delete mode 100644 kernel/include/kernel/Terminal/termios.h diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 7c750eee..009c79d1 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -68,8 +68,8 @@ namespace Kernel BAN::ErrorOr sys_exit(int status); - BAN::ErrorOr sys_gettermios(::termios*); - BAN::ErrorOr sys_settermios(const ::termios*); + BAN::ErrorOr sys_tcgetattr(int fildes, termios*); + BAN::ErrorOr sys_tcsetattr(int fildes, int optional_actions, const termios*); BAN::ErrorOr sys_fork(uintptr_t rsp, uintptr_t rip); BAN::ErrorOr sys_exec(const char* path, const char* const* argv, const char* const* envp); diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index 11545d78..f7e96ebe 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -4,18 +4,17 @@ #include #include #include -#include #include #include +#include + namespace Kernel { class TTY : public CharacterDevice { public: - void set_termios(const termios& termios) { m_termios = termios; } - termios get_termios() const { return m_termios; } virtual void set_font(const LibFont::Font&) {}; void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; } @@ -33,6 +32,10 @@ namespace Kernel void on_key_event(LibInput::KeyEvent); void handle_input_byte(uint8_t); + void get_termios(termios* termios) { *termios = m_termios; } + // FIXME: validate termios + BAN::ErrorOr set_termios(const termios* termios) { m_termios = *termios; return {}; } + virtual bool is_tty() const override { return true; } virtual uint32_t height() const = 0; @@ -53,7 +56,15 @@ namespace Kernel protected: TTY(mode_t mode, uid_t uid, gid_t gid) : CharacterDevice(mode, uid, gid) - { } + { + // FIXME: add correct baud and flags + m_termios.c_iflag = 0; + m_termios.c_oflag = 0; + m_termios.c_cflag = CS8; + m_termios.c_lflag = ECHO | ICANON; + m_termios.c_ospeed = B38400; + m_termios.c_ispeed = B38400; + } virtual void putchar_impl(uint8_t ch) = 0; virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index 949f710b..a01147e8 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include diff --git a/kernel/include/kernel/Terminal/termios.h b/kernel/include/kernel/Terminal/termios.h deleted file mode 100644 index 82f80630..00000000 --- a/kernel/include/kernel/Terminal/termios.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace Kernel -{ - - struct termios - { - bool canonical { true }; - bool echo { true }; - }; - -} diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 5830ed87..0601eee0 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -332,39 +332,38 @@ namespace Kernel ASSERT_NOT_REACHED(); } - BAN::ErrorOr Process::sys_gettermios(::termios* termios) + BAN::ErrorOr Process::sys_tcgetattr(int fildes, termios* termios) { LockGuard _(m_process_lock); - TRY(validate_pointer_access(termios, sizeof(::termios))); + TRY(validate_pointer_access(termios, sizeof(termios))); - if (!m_controlling_terminal) + auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); + if (!inode->is_tty()) return BAN::Error::from_errno(ENOTTY); - Kernel::termios ktermios = m_controlling_terminal->get_termios(); - termios->c_lflag = 0; - if (ktermios.canonical) - termios->c_lflag |= ICANON; - if (ktermios.echo) - termios->c_lflag |= ECHO; + static_cast(inode.ptr())->get_termios(termios); return 0; } - BAN::ErrorOr Process::sys_settermios(const ::termios* termios) + BAN::ErrorOr Process::sys_tcsetattr(int fildes, int optional_actions, const termios* termios) { + if (optional_actions != TCSANOW) + return BAN::Error::from_errno(EINVAL); + LockGuard _(m_process_lock); - TRY(validate_pointer_access(termios, sizeof(::termios))); + TRY(validate_pointer_access(termios, sizeof(termios))); - if (!m_controlling_terminal) + auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); + if (!inode->is_tty()) return BAN::Error::from_errno(ENOTTY); - Kernel::termios ktermios; - ktermios.echo = termios->c_lflag & ECHO; - ktermios.canonical = termios->c_lflag & ICANON; + TRY(static_cast(inode.ptr())->set_termios(termios)); + + // FIXME: SIGTTOU - m_controlling_terminal->set_termios(ktermios); return 0; } diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 0eb02f4c..3f7a22b0 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -234,7 +234,7 @@ namespace Kernel } // ^D + canonical - if (ch == '\x04' && m_termios.canonical) + if (ch == '\x04' && (m_termios.c_lflag & ICANON)) { m_output.flush = true; m_output.thread_blocker.unblock(); @@ -242,7 +242,7 @@ namespace Kernel } // backspace + canonical - if (ch == '\b' && m_termios.canonical) + if (ch == '\b' && (m_termios.c_lflag & ICANON)) { do_backspace(); return; @@ -250,7 +250,7 @@ namespace Kernel m_output.buffer[m_output.bytes++] = ch; - if (m_termios.echo) + if (m_termios.c_lflag & ECHO) { if ((ch <= 31 || ch == 127) && ch != '\n') { @@ -276,7 +276,7 @@ namespace Kernel } } - if (ch == '\n' || !m_termios.canonical) + if (ch == '\n' || !(m_termios.c_lflag & ICANON)) { m_output.flush = true; m_output.thread_blocker.unblock(); diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index 1d2c85f1..e88954ff 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -15,8 +15,8 @@ __BEGIN_DECLS O(SYS_OPENAT, openat) \ O(SYS_SEEK, seek) \ O(SYS_TELL, tell) \ - O(SYS_GET_TERMIOS, gettermios) \ - O(SYS_SET_TERMIOS, settermios) \ + O(SYS_TCGETATTR, tcgetattr) \ + O(SYS_TCSETATTR, tcsetattr) \ O(SYS_FORK, fork) \ O(SYS_EXEC, exec) \ O(SYS_SLEEP, sleep) \ diff --git a/userspace/libraries/LibC/include/termios.h b/userspace/libraries/LibC/include/termios.h index 2a0aac46..6b19e1c7 100644 --- a/userspace/libraries/LibC/include/termios.h +++ b/userspace/libraries/LibC/include/termios.h @@ -35,6 +35,8 @@ struct termios tcflag_t c_cflag; /* Control modes. */ tcflag_t c_lflag; /* Local modes. */ cc_t c_cc[NCCS]; /* Control characters. */ + speed_t c_ospeed; + speed_t c_ispeed; }; #define BRKINT 0x001 diff --git a/userspace/libraries/LibC/termios.cpp b/userspace/libraries/LibC/termios.cpp index 26715a75..e2b749dd 100644 --- a/userspace/libraries/LibC/termios.cpp +++ b/userspace/libraries/LibC/termios.cpp @@ -1,14 +1,65 @@ +#include #include #include #include -speed_t cfgetispeed(const struct termios*); +speed_t cfgetispeed(const struct termios* termios) +{ + return termios->c_ispeed; +} -speed_t cfgetospeed(const struct termios*); +speed_t cfgetospeed(const struct termios* termios) +{ + return termios->c_ospeed; +} -int cfsetispeed(struct termios*, speed_t); +static bool is_valid_speed(speed_t speed) +{ + switch (speed) + { + case B0: + case B50: + case B75: + case B110: + case B134: + case B150: + case B200: + case B300: + case B600: + case B1200: + case B1800: + case B2400: + case B4800: + case B9600: + case B19200: + case B38400: + return true; + default: + return false; + } +} -int cfsetospeed(struct termios*, speed_t); +int cfsetispeed(struct termios* termios, speed_t speed) +{ + if (!is_valid_speed(speed)) + { + errno = EINVAL; + return -1; + } + termios->c_ispeed = speed; + return 0; +} + +int cfsetospeed(struct termios* termios, speed_t speed) +{ + if (!is_valid_speed(speed)) + { + errno = EINVAL; + return -1; + } + termios->c_ospeed = speed; + return 0; +} int tcdrain(int); @@ -16,16 +67,16 @@ int tcflow(int, int); int tcflush(int, int); -int tcgetattr(int, struct termios* termios) +int tcgetattr(int fildes, struct termios* termios) { - return syscall(SYS_GET_TERMIOS, termios); + return syscall(SYS_TCGETATTR, fildes, termios); } pid_t tcgetsid(int); int tcsendbreak(int, int); -int tcsetattr(int, int, const struct termios* termios) +int tcsetattr(int fildes, int optional_actions, const struct termios* termios) { - return syscall(SYS_SET_TERMIOS, termios); + return syscall(SYS_TCSETATTR, fildes, optional_actions, termios); }