From d21bc8268b0d597fad7ca24f84cb9cabfb68dc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= <josef.soentgen@genode-labs.com> Date: Fri, 14 Aug 2020 15:44:22 +0200 Subject: [PATCH] vfs: add raw option to terminal plugin When the 'raw' attribute is set to 'yes' the terminal VFS plugin will ignore control characters. This in necessary for terminal connections that transport data that contain such characters as part of message. Fixes #3860. --- repos/os/src/lib/vfs/terminal_file_system.h | 42 ++++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/repos/os/src/lib/vfs/terminal_file_system.h b/repos/os/src/lib/vfs/terminal_file_system.h index a776891a67..dc0fa909c0 100644 --- a/repos/os/src/lib/vfs/terminal_file_system.h +++ b/repos/os/src/lib/vfs/terminal_file_system.h @@ -62,6 +62,8 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system Interrupt_handler &_interrupt_handler; + bool const _raw; + enum { READ_BUFFER_SIZE = 4000 }; typedef Genode::Ring_buffer<char, READ_BUFFER_SIZE + 1, @@ -71,7 +73,8 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system static void _fetch_data_from_terminal(Terminal::Connection &terminal, Read_buffer &read_buffer, - Interrupt_handler &interrupt_handler) + Interrupt_handler &interrupt_handler, + bool raw) { while (terminal.avail()) { @@ -93,7 +96,7 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system enum { INTERRUPT = 3 }; - if (c == INTERRUPT) { + if (c == INTERRUPT && !raw) { interrupt_handler.handle_interrupt(); } else { read_buffer.add(c); @@ -108,6 +111,8 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system Read_buffer &_read_buffer; Interrupt_handler &_interrupt_handler; + bool _raw; + bool notifying = false; bool blocked = false; @@ -117,12 +122,14 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, - int flags) + int flags, + bool raw) : Single_vfs_handle(ds, fs, alloc, flags), _terminal(terminal), _read_buffer(read_buffer), - _interrupt_handler(interrupt_handler) + _interrupt_handler(interrupt_handler), + _raw(raw) { } bool read_ready() override { @@ -133,7 +140,7 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system { if (_read_buffer.empty()) _fetch_data_from_terminal(_terminal, _read_buffer, - _interrupt_handler); + _interrupt_handler, _raw); if (_read_buffer.empty()) { blocked = true; @@ -168,9 +175,9 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system void _handle_read_avail() { /* - * Fetch as much data from the terminal as possible to detect - * user-interrupt characters (control-c), even before the VFS - * client attempts to read from the terminal. + * On non-raw sessions, fetch as much data from the terminal as + * possible to detect user-interrupt characters (control-c), even + * before the VFS client attempts to read from the terminal. * * Note that a user interrupt that follows a large chunk of data * (exceeding the capacity of the read buffer) cannot be detected @@ -180,7 +187,8 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system * situation occurs. This can be provoked by pasting a large amount * of text into the terminal. */ - _fetch_data_from_terminal(_terminal, _read_buffer, _interrupt_handler); + _fetch_data_from_terminal(_terminal, _read_buffer, _interrupt_handler, + _raw); _handle_registry.for_each([this] (Registered_handle &handle) { if (handle.blocked) { @@ -200,12 +208,14 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system Data_file_system(Genode::Entrypoint &ep, Terminal::Connection &terminal, Name const &name, - Interrupt_handler &interrupt_handler) + Interrupt_handler &interrupt_handler, + bool raw) : Single_file_system(Node_type::TRANSACTIONAL_FILE, name.string(), Node_rwx::rw(), Genode::Xml_node("<data/>")), _name(name), _ep(ep), _terminal(terminal), - _interrupt_handler(interrupt_handler) + _interrupt_handler(interrupt_handler), + _raw(raw) { /* register for read-avail notification */ _terminal.read_avail_sigh(_read_avail_handler); @@ -224,7 +234,8 @@ class Vfs::Terminal_file_system::Data_file_system : public Single_file_system try { *out_handle = new (alloc) Registered_handle(_handle_registry, _terminal, _read_buffer, - _interrupt_handler, *this, *this, alloc, flags); + _interrupt_handler, *this, *this, alloc, flags, + _raw); return OPEN_OK; } catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } @@ -271,7 +282,9 @@ struct Vfs::Terminal_file_system::Local_factory : File_system_factory, Terminal::Connection _terminal { _env, _label.string() }; - Data_file_system _data_fs { _env.ep(), _terminal, _name, *this }; + bool const _raw; + + Data_file_system _data_fs { _env.ep(), _terminal, _name, *this, _raw }; struct Info { @@ -328,7 +341,8 @@ struct Vfs::Terminal_file_system::Local_factory : File_system_factory, : _label(config.attribute_value("label", Label(""))), _name(name(config)), - _env(env.env()) + _env(env.env()), + _raw(config.attribute_value("raw", false)) { _terminal.size_changed_sigh(_size_changed_handler); _handle_size_changed();