From 546d90045489017b528f49da36c06f1266947d78 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 12 Jul 2023 19:23:06 +0200 Subject: [PATCH] libc+apps: Start implementing POSIX-compliant termios.h wrappers around tty ioctls --- apps/login.cpp | 9 ++------- apps/sh.cpp | 15 ++++---------- apps/su.cpp | 16 +++++++-------- kernel/src/fs/devices/ConsoleDevice.cpp | 5 +++++ kernel/src/thread/Thread.cpp | 5 +++++ kernel/src/thread/Thread.h | 2 ++ libc/CMakeLists.txt | 1 + libc/include/bits/termios.h | 1 + libc/include/termios.h | 26 +++++++++++++++++++++++++ libc/include/unistd.h | 6 ++++++ libc/src/termios.cpp | 17 ++++++++++++++++ libc/src/unistd.cpp | 14 +++++++++++++ 12 files changed, 90 insertions(+), 27 deletions(-) create mode 100644 libc/include/termios.h create mode 100644 libc/src/termios.cpp diff --git a/apps/login.cpp b/apps/login.cpp index e44535a2..e5d80eb4 100644 --- a/apps/login.cpp +++ b/apps/login.cpp @@ -1,10 +1,9 @@ -#include #include #include #include #include #include -#include +#include #include Result luna_main(int argc, char** argv) @@ -31,11 +30,7 @@ Result luna_main(int argc, char** argv) { signal(SIGTTOU, SIG_IGN); - if (isatty(STDIN_FILENO)) - { - pid_t pgid = getpgid(0); - ioctl(STDIN_FILENO, TIOCSPGRP, &pgid); - } + if (isatty(STDIN_FILENO)) tcsetpgrp(STDIN_FILENO, getpgid(0)); auto input = os::File::standard_input(); diff --git a/apps/sh.cpp b/apps/sh.cpp index 4e388980..80b66f1e 100644 --- a/apps/sh.cpp +++ b/apps/sh.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -12,8 +11,8 @@ #include #include #include -#include #include +#include #include using os::File; @@ -85,8 +84,7 @@ Result luna_main(int argc, char** argv) signal(SIGTTOU, SIG_IGN); signal(SIGINT, sigint_handler); - pid_t pgid = getpgid(0); - ioctl(STDIN_FILENO, TIOCSPGRP, &pgid); + tcsetpgrp(STDIN_FILENO, getpgid(0)); } while (1) @@ -138,8 +136,7 @@ Result luna_main(int argc, char** argv) if (interactive) { setpgid(0, 0); - pid_t pgid = getpgid(0); - ioctl(STDIN_FILENO, TIOCSPGRP, &pgid); + tcsetpgrp(STDIN_FILENO, getpid()); } TRY(execute_command(cmd.view())); } @@ -147,11 +144,7 @@ Result luna_main(int argc, char** argv) int status; TRY(os::Process::wait(child, &status)); - if (interactive) - { - pid_t pgid = getpgid(0); - ioctl(STDIN_FILENO, TIOCSPGRP, &pgid); - } + if (interactive) tcsetpgrp(STDIN_FILENO, getpgid(0)); if (WIFSIGNALED(status)) { diff --git a/apps/su.cpp b/apps/su.cpp index cd965894..f1602672 100644 --- a/apps/su.cpp +++ b/apps/su.cpp @@ -1,17 +1,16 @@ -#include #include #include #include #include #include -#include +#include #include static struct termios orig; void restore_terminal() { - ioctl(fileno(stdin), TCSETS, &orig); + tcsetattr(STDIN_FILENO, TCSANOW, &orig); } void signal_handler(int signo) @@ -29,14 +28,13 @@ char* getpass() return nullptr; } - pid_t pgid = getpgid(0); - ioctl(STDIN_FILENO, TIOCSPGRP, &pgid); + tcsetpgrp(STDIN_FILENO, getpgid(0)); fputs("Password: ", stdout); - if (ioctl(fileno(stdin), TCGETS, &orig) < 0) + if (tcgetattr(STDIN_FILENO, &orig) < 0) { - perror("ioctl(TCGETS)"); + perror("tcgetattr"); return nullptr; } @@ -52,9 +50,9 @@ char* getpass() struct termios tc = orig; tc.c_lflag &= ~ECHO; - if (ioctl(fileno(stdin), TCSETS, &tc) < 0) + if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0) { - perror("ioctl(TCSETS)"); + perror("tcsetattr"); return nullptr; } diff --git a/kernel/src/fs/devices/ConsoleDevice.cpp b/kernel/src/fs/devices/ConsoleDevice.cpp index be2b0f0f..bf34fa76 100644 --- a/kernel/src/fs/devices/ConsoleDevice.cpp +++ b/kernel/src/fs/devices/ConsoleDevice.cpp @@ -193,6 +193,11 @@ Result ConsoleDevice::ioctl(int request, void* arg) g_foreground_process_group = pgid; return 0; } + case TIOCGPGRP: { + pid_t pgid = g_foreground_process_group.value_or((pid_t)next_thread_id()); + if (!MemoryManager::copy_to_user_typed((pid_t*)arg, &pgid)) return err(EFAULT); + return 0; + } default: return err(EINVAL); } } diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 5d21a1d9..ad070708 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -28,6 +28,11 @@ Result new_thread() return thread; } +u64 next_thread_id() +{ + return g_next_id.load(); +} + Result Thread::allocate_fd(int min) { if (min < 0 || min >= FD_MAX) return err(EINVAL); diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index a9639d4c..0997f40e 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -159,4 +159,6 @@ bool is_in_kernel(Registers* regs); Result new_thread(); +u64 next_thread_id(); + extern LinkedList g_threads; diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 5edda97a..19d4c7d2 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -22,6 +22,7 @@ set(SOURCES src/locale.cpp src/scanf.cpp src/signal.cpp + src/termios.cpp src/sys/stat.cpp src/sys/mman.cpp src/sys/wait.cpp diff --git a/libc/include/bits/termios.h b/libc/include/bits/termios.h index 3c0572c5..311de6ed 100644 --- a/libc/include/bits/termios.h +++ b/libc/include/bits/termios.h @@ -19,5 +19,6 @@ struct termios #define TCGETS 0 #define TCSETS 1 #define TIOCSPGRP 2 +#define TIOCGPGRP 3 #endif diff --git a/libc/include/termios.h b/libc/include/termios.h new file mode 100644 index 00000000..23b8b3a9 --- /dev/null +++ b/libc/include/termios.h @@ -0,0 +1,26 @@ +/* termios.h: Terminal device control. */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#include +#include + +#define TCSANOW 0 + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Fetch attributes associated with a terminal file descriptor. */ + int tcgetattr(int fd, struct termios* termp); + + /* Set attributes associated with a terminal file descriptor. */ + int tcsetattr(int fd, int act, const struct termios* termp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h index 82ebf8da..a9548ef9 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -174,6 +174,12 @@ extern "C" /* Check whether a file descriptor refers to a terminal device. */ int isatty(int fd); + /* Fetch the process group associated with a terminal file descriptor. */ + pid_t tcgetpgrp(int fd); + + /* Set the process group associated with a terminal file descriptor. */ + int tcsetpgrp(int fd, pid_t pgrp); + #ifdef __cplusplus } #endif diff --git a/libc/src/termios.cpp b/libc/src/termios.cpp new file mode 100644 index 00000000..b97c0138 --- /dev/null +++ b/libc/src/termios.cpp @@ -0,0 +1,17 @@ +#include +#include +#include + +extern "C" +{ + int tcgetattr(int fd, struct termios* termp) + { + return ioctl(fd, TCGETS, termp); + } + + int tcsetattr(int fd, int act, const struct termios* termp) + { + check(act == TCSANOW); + return ioctl(fd, TCSETS, termp); + } +} diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index 7abba431..32c56c88 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -484,4 +486,16 @@ extern "C" } return (int)rc; } + + pid_t tcgetpgrp(int fd) + { + pid_t pgid; + if (ioctl(fd, TIOCGPGRP, &pgid) < 0) return -1; + return pgid; + } + + int tcsetpgrp(int fd, pid_t pgid) + { + return ioctl(fd, TIOCSPGRP, &pgid); + } }