From 05c9f0640c6650bcb996b3124d469d75b145b735 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 15 May 2026 16:38:36 +0300 Subject: [PATCH] Kernel/LibC: Replace terminal syscalls with ioctls isatty, tc{get,set}attr, tc{get,set}pgrp are now implemented as ioctls instead of separate syscalls --- kernel/include/kernel/Process.h | 8 +- kernel/include/kernel/Terminal/TTY.h | 10 +- kernel/kernel/Process.cpp | 118 +++--------------- kernel/kernel/Terminal/PseudoTerminal.cpp | 2 +- kernel/kernel/Terminal/TTY.cpp | 61 ++++++--- userspace/libraries/LibC/include/sys/ioctl.h | 10 +- .../libraries/LibC/include/sys/syscall.h | 5 - userspace/libraries/LibC/termios.cpp | 49 +++++--- userspace/libraries/LibC/unistd.cpp | 11 +- 9 files changed, 114 insertions(+), 160 deletions(-) diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index fea857d7..90b2ae84 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -56,6 +56,7 @@ namespace Kernel pid_t pid() const { return m_pid; } bool is_session_leader() const { return pid() == sid(); } + bool is_pgrpg_in_this_session(pid_t) const; const char* name() const { return m_cmdline.empty() ? "" : m_cmdline.front().data(); } @@ -63,9 +64,6 @@ namespace Kernel BAN::ErrorOr sys_exit(int status); - 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); @@ -186,7 +184,6 @@ namespace Kernel BAN::ErrorOr sys_smo_map(SharedMemoryObjectManager::Key); BAN::ErrorOr sys_ttyname(int fildes, char* name, size_t namesize); - BAN::ErrorOr sys_isatty(int fildes); BAN::ErrorOr sys_posix_openpt(int flags); BAN::ErrorOr sys_ptsname(int fildes, char* buffer, size_t buffer_len); @@ -218,9 +215,6 @@ namespace Kernel BAN::ErrorOr sys_pthread_self(); BAN::ErrorOr sys_pthread_kill(pthread_t thread, int signal); - BAN::ErrorOr sys_tcgetpgrp(int fd); - BAN::ErrorOr sys_tcsetpgrp(int fd, pid_t pgid); - BAN::ErrorOr sys_clock_gettime(clockid_t, timespec*); BAN::ErrorOr sys_load_keymap(const char* path); diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index bd83b2a9..ee1ee01f 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -33,9 +33,6 @@ namespace Kernel public: virtual BAN::ErrorOr set_font(LibFont::Font&&) { return BAN::Error::from_errno(EINVAL); } - void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; } - pid_t foreground_pgrp() const { return m_foreground_pgrp; } - BAN::ErrorOr tty_ctrl(int command, int flags); // for kprint @@ -52,9 +49,6 @@ namespace Kernel void on_key_event(LibInput::KeyEvent); void handle_input_byte(uint8_t); - void get_termios(termios*); - BAN::ErrorOr set_termios(const termios*); - virtual bool is_tty() const override { return true; } virtual dev_t rdev() const final override { return m_rdev; } @@ -87,10 +81,12 @@ namespace Kernel bool putchar(uint8_t ch); void do_backspace(); + termios get_termios(); + private: const dev_t m_rdev; - pid_t m_foreground_pgrp { 0 }; + BAN::Atomic m_foreground_pgrp { 0 }; struct tty_ctrl_t { diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 38381957..cf1e03c6 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -226,6 +226,23 @@ namespace Kernel ASSERT(!m_page_table); } + bool Process::is_pgrpg_in_this_session(pid_t pgrp) const + { + bool valid_pgrp = false; + for_each_process( + [&](Process& process) + { + if (process.sid() == sid() && process.pgrp() == pgrp) + { + valid_pgrp = true; + return BAN::Iteration::Break; + } + return BAN::Iteration::Continue; + } + ); + return valid_pgrp; + } + void Process::add_thread(Thread* thread) { LockGuard _(m_process_lock); @@ -624,40 +641,6 @@ namespace Kernel ASSERT_NOT_REACHED(); } - BAN::ErrorOr Process::sys_tcgetattr(int fildes, termios* user_termios) - { - auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); - if (!inode->is_tty()) - return BAN::Error::from_errno(ENOTTY); - - struct termios termios; - static_cast(inode.ptr())->get_termios(&termios); - - TRY(write_to_user(user_termios, &termios, sizeof(struct termios))); - - return 0; - } - - BAN::ErrorOr Process::sys_tcsetattr(int fildes, int optional_actions, const termios* user_termios) - { - //if (optional_actions != TCSANOW) - // return BAN::Error::from_errno(EINVAL); - (void)optional_actions; - - auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); - if (!inode->is_tty()) - return BAN::Error::from_errno(ENOTTY); - - termios termios; - TRY(read_from_user(user_termios, &termios, sizeof(struct termios))); - - TRY(static_cast(inode.ptr())->set_termios(&termios)); - - // FIXME: SIGTTOU - - return 0; - } - BAN::ErrorOr Process::sys_fork(uintptr_t sp, uintptr_t ip) { auto page_table = BAN::UniqPtr::adopt(TRY(PageTable::create_userspace())); @@ -2764,15 +2747,6 @@ namespace Kernel return 0; } - BAN::ErrorOr Process::sys_isatty(int fildes) - { - LockGuard _(m_process_lock); - auto inode = TRY(m_open_file_descriptors.inode_of(fildes)); - if (!inode->is_tty()) - return BAN::Error::from_errno(ENOTTY); - return 0; - } - BAN::ErrorOr Process::sys_posix_openpt(int flags) { if (flags & ~(O_RDWR | O_NOCTTY)) @@ -3449,64 +3423,6 @@ namespace Kernel return BAN::Error::from_errno(ESRCH); } - BAN::ErrorOr Process::sys_tcgetpgrp(int fd) - { - LockGuard _(m_process_lock); - - auto inode = TRY(m_open_file_descriptors.inode_of(fd)); - - // NOTE: This is a hack but I'm not sure how terminal is supposted to get - // slave's foreground pgroup while not having controlling terminal - if (TRY(m_open_file_descriptors.path_of(fd)) == ""_sv) - return TRY(static_cast(inode.ptr())->slave())->foreground_pgrp(); - - if (!m_controlling_terminal) - return BAN::Error::from_errno(ENOTTY); - - if (!inode->is_tty()) - return BAN::Error::from_errno(ENOTTY); - - auto* tty = static_cast(inode.ptr()); - if (tty != m_controlling_terminal.ptr()) - return BAN::Error::from_errno(ENOTTY); - - return tty->foreground_pgrp(); - } - - BAN::ErrorOr Process::sys_tcsetpgrp(int fd, pid_t pgrp) - { - LockGuard _(m_process_lock); - - if (!m_controlling_terminal) - return BAN::Error::from_errno(ENOTTY); - - bool valid_pgrp = false; - for_each_process( - [&](Process& process) - { - if (process.sid() == sid() && process.pgrp() == pgrp) - { - valid_pgrp = true; - return BAN::Iteration::Break; - } - return BAN::Iteration::Continue; - } - ); - if (!valid_pgrp) - return BAN::Error::from_errno(EPERM); - - auto inode = TRY(m_open_file_descriptors.inode_of(fd)); - if (!inode->is_tty()) - return BAN::Error::from_errno(ENOTTY); - - auto* tty = static_cast(inode.ptr()); - if (tty != m_controlling_terminal.ptr()) - return BAN::Error::from_errno(ENOTTY); - - tty->set_foreground_pgrp(pgrp); - return 0; - } - BAN::ErrorOr Process::sys_setuid(uid_t uid) { if (uid < 0 || uid >= 1'000'000'000) diff --git a/kernel/kernel/Terminal/PseudoTerminal.cpp b/kernel/kernel/Terminal/PseudoTerminal.cpp index 1f37b2b2..090548a5 100644 --- a/kernel/kernel/Terminal/PseudoTerminal.cpp +++ b/kernel/kernel/Terminal/PseudoTerminal.cpp @@ -173,7 +173,7 @@ namespace Kernel return BAN::Error::from_errno(ENODEV); } - return BAN::Error::from_errno(ENOTSUP); + return CharacterDevice::ioctl(request, argument); } PseudoTerminalSlave::PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t mode, uid_t uid, gid_t gid) diff --git a/kernel/kernel/Terminal/TTY.cpp b/kernel/kernel/Terminal/TTY.cpp index 38da8ff3..276c0d83 100644 --- a/kernel/kernel/Terminal/TTY.cpp +++ b/kernel/kernel/Terminal/TTY.cpp @@ -210,8 +210,47 @@ namespace Kernel (void)Process::kill(-m_foreground_pgrp, SIGWINCH); return 0; } + case TCGETS: + { + SpinLockGuard _(m_termios_lock); + auto* termios = static_cast(argument); + *termios = m_termios; + return 0; + } + case TCSETSW: + case TCSETSF: + dwarnln("TODO: proper TCSETSW/TCSETSWF"); + [[fallthrough]]; + case TCSETS: + { + // FIXME: do some validation + SpinLockGuard _(m_termios_lock); + const auto* termios = static_cast(argument); + m_termios = *termios; + return 0; + } + case TIOCGPGRP: + { + pid_t* pgrp = static_cast(argument); + *pgrp = m_foreground_pgrp.load(); + return 0; + } + case TIOCSPGRP: + { + const pid_t pgrp = *static_cast(argument); + + if (!Process::current().is_pgrpg_in_this_session(pgrp)) + return BAN::Error::from_errno(EPERM); + + if (this != Process::current().controlling_terminal().ptr()) + return BAN::Error::from_errno(ENOTTY); + + m_foreground_pgrp = pgrp; + return 0; + } } - return BAN::Error::from_errno(ENOTSUP); + + return CharacterDevice::ioctl(request, argument); } void TTY::on_key_event(LibInput::RawKeyEvent event) @@ -234,19 +273,10 @@ namespace Kernel after_write(); } - void TTY::get_termios(termios* termios) + termios TTY::get_termios() { SpinLockGuard _(m_termios_lock); - *termios = m_termios; - } - - BAN::ErrorOr TTY::set_termios(const termios* termios) - { - // FIXME: do some validation - - SpinLockGuard _(m_termios_lock); - m_termios = *termios; - return {}; + return m_termios; } void TTY::handle_input_byte(uint8_t ch) @@ -256,9 +286,7 @@ namespace Kernel LockGuard _0(m_mutex); - termios termios; - get_termios(&termios); - + const auto termios = get_termios(); if ((termios.c_iflag & ISTRIP)) ch &= 0x7F; @@ -394,8 +422,7 @@ namespace Kernel if (!m_tty_ctrl.draw_graphics) return true; - termios termios; - get_termios(&termios); + const auto termios = get_termios(); SpinLockGuard _1(m_write_lock); if (termios.c_oflag & OPOST) diff --git a/userspace/libraries/LibC/include/sys/ioctl.h b/userspace/libraries/LibC/include/sys/ioctl.h index 0a6366c3..d918ba8e 100644 --- a/userspace/libraries/LibC/include/sys/ioctl.h +++ b/userspace/libraries/LibC/include/sys/ioctl.h @@ -49,8 +49,14 @@ struct winsize unsigned short ws_xpixel; /* unused by kernel */ unsigned short ws_ypixel; /* unused by kernel */ }; -#define TIOCGWINSZ 50 -#define TIOCSWINSZ 51 +#define TIOCGWINSZ 50 +#define TIOCSWINSZ 51 +#define TCGETS 52 +#define TCSETS 53 +#define TCSETSW 54 +#define TCSETSF 55 +#define TIOCGPGRP 56 +#define TIOCSPGRP 57 struct snd_volume_info { diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index 4798b58c..be6c98d6 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -14,8 +14,6 @@ __BEGIN_DECLS O(SYS_SEEK, seek) \ O(SYS_TELL, tell) \ O(SYS_RENAMEAT, renameat) \ - O(SYS_TCGETATTR, tcgetattr) \ - O(SYS_TCSETATTR, tcsetattr) \ O(SYS_FORK, fork) \ O(SYS_EXEC, exec) \ O(SYS_SLEEP, sleep) \ @@ -39,8 +37,6 @@ __BEGIN_DECLS O(SYS_PIPE, pipe) \ O(SYS_DUP2, dup2) \ O(SYS_KILL, kill) \ - O(SYS_TCGETPGRP, tcgetpgrp) \ - O(SYS_TCSETPGRP, tcsetpgrp) \ O(SYS_GET_PPID, getppid) \ O(SYS_GET_PID, getpid) \ O(SYS_GET_PGID, getpgid) \ @@ -79,7 +75,6 @@ __BEGIN_DECLS O(SYS_SMO_CREATE, smo_create) \ O(SYS_SMO_DELETE, smo_delete) \ O(SYS_SMO_MAP, smo_map) \ - O(SYS_ISATTY, isatty) \ O(SYS_GETSOCKNAME, getsockname) \ O(SYS_GETPEERNAME, getpeername) \ O(SYS_GETSOCKOPT, getsockopt) \ diff --git a/userspace/libraries/LibC/termios.cpp b/userspace/libraries/LibC/termios.cpp index d6f1b250..768bc050 100644 --- a/userspace/libraries/LibC/termios.cpp +++ b/userspace/libraries/LibC/termios.cpp @@ -3,20 +3,11 @@ #include #include +#include #include #include #include -speed_t cfgetispeed(const struct termios* termios) -{ - return termios->c_ispeed; -} - -speed_t cfgetospeed(const struct termios* termios) -{ - return termios->c_ospeed; -} - static bool is_valid_speed(speed_t speed) { switch (speed) @@ -43,6 +34,16 @@ static bool is_valid_speed(speed_t speed) } } +speed_t cfgetispeed(const struct termios* termios) +{ + return termios->c_ispeed; +} + +speed_t cfgetospeed(const struct termios* termios) +{ + return termios->c_ospeed; +} + int cfsetispeed(struct termios* termios, speed_t speed) { if (!is_valid_speed(speed)) @@ -87,18 +88,32 @@ int tcflush(int fd, int queue_selector) int tcgetattr(int fildes, struct termios* termios) { - return syscall(SYS_TCGETATTR, fildes, termios); + return ioctl(fildes, TCGETS, termios); } -pid_t tcgetsid(int); +int tcsetattr(int fildes, int optional_actions, const struct termios* termios) +{ + int ioctl_num; + switch (optional_actions) + { + case TCSANOW: + ioctl_num = TCSETS; + break; + case TCSADRAIN: + ioctl_num = TCSETSW; + break; + case TCSAFLUSH: + ioctl_num = TCSETSF; + break; + default: + errno = EINVAL; + return -1; + } + return ioctl(fildes, ioctl_num, termios); +} int tcsendbreak(int fd, int duration) { dwarnln("FIXME: tcsendbreak({}, {})", fd, duration); return -1; } - -int tcsetattr(int fildes, int optional_actions, const struct termios* termios) -{ - return syscall(SYS_TCSETATTR, fildes, optional_actions, termios); -} diff --git a/userspace/libraries/LibC/unistd.cpp b/userspace/libraries/LibC/unistd.cpp index 09fbbfcb..c7700919 100644 --- a/userspace/libraries/LibC/unistd.cpp +++ b/userspace/libraries/LibC/unistd.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -349,7 +350,8 @@ int dup2(int fildes, int fildes2) int isatty(int fildes) { - return syscall(SYS_ISATTY, fildes) >= 0; + struct termios termios; + return tcgetattr(fildes, &termios) + 1; } int gethostname(char* name, size_t namelen) @@ -838,7 +840,10 @@ pid_t getsid(pid_t pid) int tcgetpgrp(int fildes) { - return syscall(SYS_TCGETPGRP, fildes); + pid_t pgrp; + if (ioctl(fildes, TIOCGPGRP, &pgrp) == -1) + return -1; + return pgrp; } int seteuid(uid_t uid) @@ -889,7 +894,7 @@ int setpgid(pid_t pid, pid_t pgid) int tcsetpgrp(int fildes, pid_t pgid_id) { - return syscall(SYS_TCSETPGRP, fildes, pgid_id); + return ioctl(fildes, TIOCSPGRP, &pgid_id); } char* getlogin(void)