mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 22:25:07 +00:00
Kernel: Perform output processing on echo
Previously, we would echo characters back just as they were passed to us, even in canonical mode. This caused newlines to not work correctly in some programs. Fixes #7802
This commit is contained in:
parent
42fcc2219d
commit
169e93f0a7
2 changed files with 32 additions and 13 deletions
|
@ -90,22 +90,17 @@ KResultOr<size_t> TTY::write(FileDescription&, u64, const UserOrKernelBuffer& bu
|
|||
constexpr size_t num_chars = 256;
|
||||
return buffer.read_buffered<num_chars>(size, [&](u8 const* data, size_t buffer_bytes) {
|
||||
u8 modified_data[num_chars * 2];
|
||||
size_t extra_chars = 0;
|
||||
size_t modified_data_size = 0;
|
||||
for (size_t i = 0; i < buffer_bytes; ++i) {
|
||||
auto ch = data[i];
|
||||
if (m_termios.c_oflag & OPOST) {
|
||||
if (ch == '\n' && (m_termios.c_oflag & ONLCR)) {
|
||||
modified_data[i + extra_chars] = '\r';
|
||||
extra_chars++;
|
||||
}
|
||||
}
|
||||
modified_data[i + extra_chars] = ch;
|
||||
process_output(data[i], [this, &modified_data, &modified_data_size](u8 out_ch) {
|
||||
modified_data[modified_data_size++] = out_ch;
|
||||
});
|
||||
}
|
||||
ssize_t bytes_written = on_tty_write(UserOrKernelBuffer::for_kernel_buffer(modified_data), buffer_bytes + extra_chars);
|
||||
ssize_t bytes_written = on_tty_write(UserOrKernelBuffer::for_kernel_buffer(modified_data), modified_data_size);
|
||||
VERIFY(bytes_written != 0);
|
||||
if (bytes_written < 0 || !(m_termios.c_oflag & OPOST) || !(m_termios.c_oflag & ONLCR))
|
||||
return bytes_written;
|
||||
if ((size_t)bytes_written == buffer_bytes + extra_chars)
|
||||
if ((size_t)bytes_written == modified_data_size)
|
||||
return (ssize_t)buffer_bytes;
|
||||
|
||||
// Degenerate case where we converted some newlines and encountered a partial write
|
||||
|
@ -127,6 +122,23 @@ KResultOr<size_t> TTY::write(FileDescription&, u64, const UserOrKernelBuffer& bu
|
|||
});
|
||||
}
|
||||
|
||||
void TTY::echo_with_processing(u8 ch)
|
||||
{
|
||||
process_output(ch, [this](u8 out_ch) { echo(out_ch); });
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
void TTY::process_output(u8 ch, Functor put_char)
|
||||
{
|
||||
if (m_termios.c_oflag & OPOST) {
|
||||
if (ch == '\n' && (m_termios.c_oflag & ONLCR))
|
||||
put_char('\r');
|
||||
put_char(ch);
|
||||
} else {
|
||||
put_char(ch);
|
||||
}
|
||||
}
|
||||
|
||||
bool TTY::can_read(const FileDescription&, size_t) const
|
||||
{
|
||||
if (in_canonical_mode()) {
|
||||
|
@ -239,7 +251,8 @@ void TTY::emit(u8 ch, bool do_evaluate_block_conditions)
|
|||
|
||||
if (ch == '\n') {
|
||||
if (m_termios.c_lflag & ECHO || m_termios.c_lflag & ECHONL)
|
||||
echo('\n');
|
||||
echo_with_processing('\n');
|
||||
|
||||
set_special_bit();
|
||||
m_input_buffer.enqueue('\n');
|
||||
m_available_lines++;
|
||||
|
@ -254,7 +267,7 @@ void TTY::emit(u8 ch, bool do_evaluate_block_conditions)
|
|||
|
||||
m_input_buffer.enqueue(ch);
|
||||
if (m_termios.c_lflag & ECHO)
|
||||
echo(ch);
|
||||
echo_with_processing(ch);
|
||||
}
|
||||
|
||||
bool TTY::can_do_backspace() const
|
||||
|
@ -271,6 +284,7 @@ void TTY::do_backspace()
|
|||
{
|
||||
if (can_do_backspace()) {
|
||||
m_input_buffer.dequeue_end();
|
||||
// We deliberately don't process the output here.
|
||||
echo(8);
|
||||
echo(' ');
|
||||
echo(8);
|
||||
|
@ -318,6 +332,7 @@ void TTY::kill_line()
|
|||
|
||||
void TTY::erase_character()
|
||||
{
|
||||
// We deliberately don't process the output here.
|
||||
echo(m_termios.c_cc[VERASE]);
|
||||
echo(' ');
|
||||
echo(m_termios.c_cc[VERASE]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue