From 71f90695c29d51ba7fab0fd4f6860df7c997547f Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 30 Apr 2021 04:45:27 +0200 Subject: [PATCH] Kernel: Implement support for PTY flags ICRNL, OPOST and ONLCR These are used by OpenSSH. Without those flags new-lines are all jumbled in the output. --- Kernel/TTY/TTY.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/Kernel/TTY/TTY.cpp b/Kernel/TTY/TTY.cpp index ee03850d65..020150c86f 100644 --- a/Kernel/TTY/TTY.cpp +++ b/Kernel/TTY/TTY.cpp @@ -68,8 +68,14 @@ KResultOr TTY::read(FileDescription&, u64, UserOrKernelBuffer& buffer, s }); } else { nwritten = buffer.write_buffered<512>(size, [&](u8* data, size_t data_size) { - for (size_t i = 0; i < data_size; i++) - data[i] = m_input_buffer.dequeue(); + for (size_t i = 0; i < data_size; i++) { + auto ch = m_input_buffer.dequeue(); + if (ch == '\r' && m_termios.c_iflag & ICRNL) + ch = '\n'; + else if (ch == '\n' && m_termios.c_iflag & INLCR) + ch = '\r'; + data[i] = ch; + } return (ssize_t)data_size; }); } @@ -87,8 +93,23 @@ KResultOr TTY::write(FileDescription&, u64, const UserOrKernelBuffer& bu return EINTR; } - on_tty_write(buffer, size); - return size; + const size_t num_chars = 256; + ssize_t nread = buffer.read_buffered((size_t)size, [&](const u8* data, size_t buffer_bytes) { + u8 modified_data[num_chars * 2]; + size_t extra_chars = 0; + for (size_t i = 0; i < buffer_bytes; ++i) { + auto ch = data[i]; + if (ch == '\n' && (m_termios.c_oflag & (OPOST | ONLCR))) { + modified_data[i + extra_chars] = '\r'; + extra_chars++; + } + modified_data[i + extra_chars] = ch; + } + on_tty_write(UserOrKernelBuffer::for_kernel_buffer(modified_data), buffer_bytes + extra_chars); + return (ssize_t)buffer_bytes; + }); + + return nread; } bool TTY::can_read(const FileDescription&, size_t) const @@ -284,7 +305,7 @@ void TTY::set_termios(const termios& t) { m_termios = t; - dbgln_if(TTY_DEBUG, "{} set_termios: ECHO={}, ISIG={}, ICANON={}, ECHOE={}, ECHOK={}, ECHONL={}, ISTRIP={}, ICRNL={}, INLCR={}, IGNCR={}", + dbgln_if(TTY_DEBUG, "{} set_termios: ECHO={}, ISIG={}, ICANON={}, ECHOE={}, ECHOK={}, ECHONL={}, ISTRIP={}, ICRNL={}, INLCR={}, IGNCR={}, OPOST={}, ONLCR={}", tty_name(), should_echo_input(), should_generate_signals(), @@ -295,7 +316,9 @@ void TTY::set_termios(const termios& t) ((m_termios.c_iflag & ISTRIP) != 0), ((m_termios.c_iflag & ICRNL) != 0), ((m_termios.c_iflag & INLCR) != 0), - ((m_termios.c_iflag & IGNCR) != 0)); + ((m_termios.c_iflag & IGNCR) != 0), + ((m_termios.c_oflag & OPOST) != 0), + ((m_termios.c_oflag & ONLCR) != 0)); } int TTY::ioctl(FileDescription&, unsigned request, FlatPtr arg)