From a788e85c0997cfb50fae0b1ec0b70ef68f461ded Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 16 Nov 2018 20:18:58 +0100 Subject: [PATCH] Refactor TTY signal generation a bit. We now respect the VINTR and VQUIT control characters in the termios. --- Kernel/Keyboard.cpp | 2 +- Kernel/Process.cpp | 5 +++++ Kernel/TTY.cpp | 35 +++++++++++++++++++++++------------ Kernel/TTY.h | 11 ++++++----- Kernel/VirtualConsole.cpp | 22 +++++++++++----------- Kernel/VirtualConsole.h | 2 +- VirtualFileSystem/UnixTypes.h | 4 ++++ 7 files changed, 51 insertions(+), 30 deletions(-) diff --git a/Kernel/Keyboard.cpp b/Kernel/Keyboard.cpp index 9768de481a..fa901fe210 100644 --- a/Kernel/Keyboard.cpp +++ b/Kernel/Keyboard.cpp @@ -82,7 +82,7 @@ void Keyboard::handleIRQ() else if (m_modifiers & Mod_Shift) emit(shift_map[ch]); else if (m_modifiers & Mod_Ctrl) - emit(shift_map[ch]); + emit(map[ch]); } //break; } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index afdab83101..5d0b290164 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -777,6 +777,11 @@ void Process::dispatch_signal(byte signal) return terminate_due_to_signal(signal); } + if (handler_laddr.asPtr() == SIG_IGN) { + dbgprintf("%s(%u) ignored signal %u\n", name().characters(), pid(), signal); + return; + } + Scheduler::prepare_to_modify_tss(*this); word ret_cs = m_tss.cs; diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index 1067f72f58..ebd5146d42 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -37,6 +37,8 @@ TTY::TTY(unsigned major, unsigned minor) { memset(&m_termios, 0, sizeof(m_termios)); m_termios.c_lflag |= ISIG | ECHO; + static const char default_cc[32] = "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"; + memcpy(m_termios.c_cc, default_cc, sizeof(default_cc)); } TTY::~TTY() @@ -64,23 +66,32 @@ bool TTY::hasDataAvailableForRead() const void TTY::emit(byte ch) { + if (should_generate_signals()) { + if (ch == m_termios.c_cc[VINTR]) { + dbgprintf("%s: VINTR pressed!\n", ttyName().characters()); + generate_signal(SIGINT); + return; + } + if (ch == m_termios.c_cc[VQUIT]) { + dbgprintf("%s: VQUIT pressed!\n", ttyName().characters()); + generate_signal(SIGQUIT); + return; + } + } m_buffer.write(&ch, 1); } -void TTY::interrupt() +void TTY::generate_signal(int signal) { - if (!should_generate_signals()) + if (!pgid()) return; - dbgprintf("%s: Interrupt ^C pressed!\n", ttyName().characters()); - if (pgid()) { - dbgprintf("%s: Send SIGINT to everyone in pgrp %d\n", ttyName().characters(), pgid()); - InterruptDisabler disabler; - Process::for_each_in_pgrp(pgid(), [this] (auto& process) { - dbgprintf("%s: Send SIGINT to %d\n", ttyName().characters(), process.pid()); - process.send_signal(SIGINT, nullptr); - return true; - }); - } + dbgprintf("%s: Send signal %d to everyone in pgrp %d\n", ttyName().characters(), signal, pgid()); + InterruptDisabler disabler; // FIXME: Iterate over a set of process handles instead? + Process::for_each_in_pgrp(pgid(), [&] (auto& process) { + dbgprintf("%s: Send signal %d to %d\n", ttyName().characters(), signal, process.pid()); + process.send_signal(signal, nullptr); + return true; + }); } void TTY::set_termios(const Unix::termios& t) diff --git a/Kernel/TTY.h b/Kernel/TTY.h index 9c3dfa2c21..e1d5f36874 100644 --- a/Kernel/TTY.h +++ b/Kernel/TTY.h @@ -49,16 +49,17 @@ public: bool in_canonical_mode() const { return m_termios.c_lflag & ICANON; } protected: - virtual bool isTTY() const final override { return true; } + virtual void onTTYWrite(const byte*, size_t) = 0; TTY(unsigned major, unsigned minor); void emit(byte); - virtual void onTTYWrite(const byte*, size_t) = 0; - - void interrupt(); - private: + // ^CharacterDevice + virtual bool isTTY() const final override { return true; } + + void generate_signal(int signal); + DoubleBuffer m_buffer; pid_t m_pgid { 0 }; Unix::termios m_termios; diff --git a/Kernel/VirtualConsole.cpp b/Kernel/VirtualConsole.cpp index 16b9b9160e..f9f3df9435 100644 --- a/Kernel/VirtualConsole.cpp +++ b/Kernel/VirtualConsole.cpp @@ -378,11 +378,8 @@ void VirtualConsole::put_character_at(unsigned row, unsigned column, byte ch) } } -void VirtualConsole::on_char(byte ch, bool shouldEmit) +void VirtualConsole::on_char(byte ch) { - if (shouldEmit) - emit(ch); - switch (m_escape_state) { case ExpectBracket: if (ch == '[') @@ -445,12 +442,15 @@ void VirtualConsole::on_char(byte ch, bool shouldEmit) void VirtualConsole::onKeyPress(Keyboard::Key key) { - if (key.ctrl() && key.character == 'C') { - interrupt(); - return; + if (key.ctrl()) { + if (key.character >= 'a' && key.character <= 'z') { + emit(key.character - 'a' + 1); + return; + } else if (key.character == '\\') { + emit(0x1c); + return; + } } - if (key.ctrl()) - emit('^'); emit(key.character); } @@ -459,7 +459,7 @@ void VirtualConsole::onConsoleReceive(byte ch) InterruptDisabler disabler; auto old_attribute = m_current_attribute; m_current_attribute = 0x03; - on_char(ch, false); + on_char(ch); m_current_attribute = old_attribute; } @@ -467,7 +467,7 @@ void VirtualConsole::onTTYWrite(const byte* data, size_t size) { InterruptDisabler disabler; for (size_t i = 0; i < size; ++i) - on_char(data[i], false); + on_char(data[i]); } String VirtualConsole::ttyName() const diff --git a/Kernel/VirtualConsole.h b/Kernel/VirtualConsole.h index 01d0d6662f..4aae3bad0e 100644 --- a/Kernel/VirtualConsole.h +++ b/Kernel/VirtualConsole.h @@ -27,7 +27,7 @@ private: virtual String ttyName() const override; void set_active(bool); - void on_char(byte, bool shouldEmit); + void on_char(byte); void get_vga_cursor(byte& row, byte& column); void flush_vga_cursor(); diff --git a/VirtualFileSystem/UnixTypes.h b/VirtualFileSystem/UnixTypes.h index 954854a763..a02cac4ae9 100644 --- a/VirtualFileSystem/UnixTypes.h +++ b/VirtualFileSystem/UnixTypes.h @@ -4,6 +4,10 @@ extern "C" { namespace Unix { +#define SIG_DFL ((void*)0) +#define SIG_ERR ((void*)-1) +#define SIG_IGN ((void*)1) + #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2