mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:08:11 +00:00
Refactor TTY signal generation a bit.
We now respect the VINTR and VQUIT control characters in the termios.
This commit is contained in:
parent
4e2c2b9748
commit
a788e85c09
7 changed files with 51 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
11
Kernel/TTY.h
11
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue