Compare commits
3 Commits
755d41ca4e
...
775c77c0fa
Author | SHA1 | Date |
---|---|---|
|
775c77c0fa | |
|
fb466b5af7 | |
|
e473118ec8 |
|
@ -12,6 +12,20 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
#define TTY_DEFAULT_TERMIOS_CC { \
|
||||
[VEOF] = '\x04', /* ctrl+D */ \
|
||||
[VEOL] = '\0', \
|
||||
[VERASE] = '\b', \
|
||||
[VINTR] = '\x03', /* ctrl+C */ \
|
||||
[VKILL] = '\x15', /* ctrl+U */ \
|
||||
[VMIN] = 0, \
|
||||
[VQUIT] = '\x1c', /* ctrl+\ */ \
|
||||
[VSTART] = '\x11', /* ctrl+Q */ \
|
||||
[VSTOP] = '\x13', /* ctrl+S */ \
|
||||
[VSUSP] = '\x1a', /* ctrl+Z */ \
|
||||
[VTIME] = 0 \
|
||||
}
|
||||
|
||||
class TTY : public CharacterDevice
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -162,8 +162,8 @@ namespace Kernel
|
|||
.c_iflag = 0,
|
||||
.c_oflag = 0,
|
||||
.c_cflag = CS8,
|
||||
.c_lflag = ECHO | ICANON,
|
||||
.c_cc = {},
|
||||
.c_lflag = ECHO | ICANON | ISIG,
|
||||
.c_cc = TTY_DEFAULT_TERMIOS_CC,
|
||||
.c_ospeed = B38400,
|
||||
.c_ispeed = B38400,
|
||||
}, mode, uid, gid)
|
||||
|
|
|
@ -174,8 +174,8 @@ namespace Kernel
|
|||
.c_iflag = ICRNL,
|
||||
.c_oflag = OPOST | ONLCR,
|
||||
.c_cflag = CS8,
|
||||
.c_lflag = ECHO | ICANON,
|
||||
.c_cc = {},
|
||||
.c_lflag = ECHO | ICANON | ISIG,
|
||||
.c_cc = TTY_DEFAULT_TERMIOS_CC,
|
||||
.c_ospeed = B38400,
|
||||
.c_ispeed = B38400,
|
||||
}, 0600, 0, 0)
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include <sys/epoll.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#define NL '\n'
|
||||
#define CR '\r'
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -216,53 +219,85 @@ namespace Kernel
|
|||
|
||||
void TTY::handle_input_byte(uint8_t ch)
|
||||
{
|
||||
if (ch == 0)
|
||||
if (ch == _POSIX_VDISABLE)
|
||||
return;
|
||||
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
if ((m_termios.c_iflag & ISTRIP))
|
||||
ch &= 0x7F;
|
||||
if ((m_termios.c_iflag & IGNCR) && ch == '\r')
|
||||
return;
|
||||
uint8_t conv = ch;
|
||||
if ((m_termios.c_iflag & ICRNL) && ch == '\r')
|
||||
conv = '\n';
|
||||
if ((m_termios.c_iflag & INLCR) && ch == '\n')
|
||||
conv = '\r';
|
||||
ch = conv;
|
||||
|
||||
// ^C
|
||||
if (ch == '\x03')
|
||||
if (m_termios.c_lflag & ICANON)
|
||||
{
|
||||
if (auto ret = Process::kill(-m_foreground_pgrp, SIGINT); ret.is_error())
|
||||
dwarnln("TTY: {}", ret.error());
|
||||
return;
|
||||
if ((m_termios.c_iflag & ISTRIP))
|
||||
ch &= 0x7F;
|
||||
if ((m_termios.c_iflag & IGNCR) && ch == CR)
|
||||
return;
|
||||
uint8_t conv = ch;
|
||||
if ((m_termios.c_iflag & ICRNL) && ch == CR)
|
||||
conv = NL;
|
||||
if ((m_termios.c_iflag & INLCR) && ch == NL)
|
||||
conv = CR;
|
||||
ch = conv;
|
||||
}
|
||||
|
||||
// ^D + canonical
|
||||
if (ch == '\x04' && (m_termios.c_lflag & ICANON))
|
||||
if (m_termios.c_lflag & ISIG)
|
||||
{
|
||||
m_output.flush = true;
|
||||
epoll_notify(EPOLLIN);
|
||||
m_output.thread_blocker.unblock();
|
||||
return;
|
||||
int sig = -1;
|
||||
if (ch == m_termios.c_cc[VINTR])
|
||||
sig = SIGINT;
|
||||
if (ch == m_termios.c_cc[VQUIT])
|
||||
sig = SIGQUIT;
|
||||
if (ch == m_termios.c_cc[VSUSP])
|
||||
sig = SIGTSTP;
|
||||
if (sig != -1)
|
||||
{
|
||||
if (auto ret = Process::kill(-m_foreground_pgrp, sig); ret.is_error())
|
||||
dwarnln("TTY: {}", ret.error());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// backspace + canonical
|
||||
if (ch == '\b' && (m_termios.c_lflag & ICANON))
|
||||
bool should_append = true;
|
||||
bool should_flush = false;
|
||||
bool force_echo = false;
|
||||
|
||||
if (!(m_termios.c_lflag & ICANON))
|
||||
should_flush = true;
|
||||
else
|
||||
{
|
||||
do_backspace();
|
||||
return;
|
||||
if (ch == m_termios.c_cc[VERASE] && (m_termios.c_lflag & ECHOE))
|
||||
return do_backspace();
|
||||
|
||||
//if (ch == m_termios.c_cc[VKILL] && (m_termios.c_lflag & ECHOK))
|
||||
// ;
|
||||
|
||||
if (ch == m_termios.c_cc[VEOF])
|
||||
{
|
||||
should_append = false;
|
||||
should_flush = true;
|
||||
}
|
||||
|
||||
if (ch == NL || ch == m_termios.c_cc[VEOL])
|
||||
{
|
||||
should_append = true;
|
||||
should_flush = true;
|
||||
force_echo = !!(m_termios.c_lflag & ECHONL);
|
||||
ch = NL;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: don't ignore these bytes
|
||||
if (m_output.bytes >= m_output.buffer.size())
|
||||
return;
|
||||
// TODO: terminal suspension with VSTOP/VSTART
|
||||
|
||||
m_output.buffer[m_output.bytes++] = ch;
|
||||
if (should_append)
|
||||
{
|
||||
// FIXME: don't ignore these bytes
|
||||
if (m_output.bytes >= m_output.buffer.size())
|
||||
{
|
||||
dwarnln("TTY input full");
|
||||
return;
|
||||
}
|
||||
m_output.buffer[m_output.bytes++] = ch;
|
||||
}
|
||||
|
||||
if (m_termios.c_lflag & ECHO)
|
||||
if (force_echo || (m_termios.c_lflag & ECHO))
|
||||
{
|
||||
if ((ch <= 31 || ch == 127) && ch != '\n')
|
||||
{
|
||||
|
@ -288,7 +323,7 @@ namespace Kernel
|
|||
}
|
||||
}
|
||||
|
||||
if (ch == '\n' || !(m_termios.c_lflag & ICANON) || m_output.bytes == m_output.buffer.size())
|
||||
if (should_flush)
|
||||
{
|
||||
m_output.flush = true;
|
||||
epoll_notify(EPOLLIN);
|
||||
|
@ -346,10 +381,10 @@ namespace Kernel
|
|||
return true;
|
||||
if (m_termios.c_oflag & OPOST)
|
||||
{
|
||||
if ((m_termios.c_oflag & ONLCR) && ch == '\n')
|
||||
return putchar_impl('\r') && putchar_impl('\n');
|
||||
if ((m_termios.c_oflag & OCRNL) && ch == '\r')
|
||||
return putchar_impl('\n');
|
||||
if ((m_termios.c_oflag & ONLCR) && ch == NL)
|
||||
return putchar_impl(CR) && putchar_impl(NL);
|
||||
if ((m_termios.c_oflag & OCRNL) && ch == CR)
|
||||
return putchar_impl(NL);
|
||||
}
|
||||
return putchar_impl(ch);
|
||||
}
|
||||
|
@ -372,7 +407,7 @@ namespace Kernel
|
|||
size_t to_copy = max_to_copy;
|
||||
if (m_termios.c_lflag & ICANON)
|
||||
for (to_copy = 1; to_copy < max_to_copy; to_copy++)
|
||||
if (m_output.buffer[to_copy - 1] == '\n')
|
||||
if (m_output.buffer[to_copy - 1] == NL)
|
||||
break;
|
||||
|
||||
memcpy(buffer.data(), m_output.buffer.data(), to_copy);
|
||||
|
|
|
@ -40,8 +40,8 @@ namespace Kernel
|
|||
.c_iflag = 0,
|
||||
.c_oflag = 0,
|
||||
.c_cflag = CS8,
|
||||
.c_lflag = ECHO | ICANON,
|
||||
.c_cc = {},
|
||||
.c_lflag = ECHO | ICANON | ISIG,
|
||||
.c_cc = TTY_DEFAULT_TERMIOS_CC,
|
||||
.c_ospeed = B38400,
|
||||
.c_ispeed = B38400,
|
||||
}, 0600, 0, 0)
|
||||
|
|
|
@ -23,6 +23,7 @@ set(USERSPACE_PROGRAMS
|
|||
ls
|
||||
meminfo
|
||||
mkdir
|
||||
nologin
|
||||
nslookup
|
||||
poweroff
|
||||
ProgramLauncher
|
||||
|
|
|
@ -382,7 +382,17 @@ BAN::Optional<BAN::String> Input::get_input(BAN::Optional<BAN::StringView> custo
|
|||
continue;
|
||||
}
|
||||
|
||||
switch (ch)
|
||||
if (ch == m_backspace)
|
||||
{
|
||||
if (m_buffer_col <= 0)
|
||||
continue;
|
||||
while ((m_buffers[m_buffer_index][m_buffer_col - 1] & 0xC0) == 0x80)
|
||||
m_buffers[m_buffer_index].remove(--m_buffer_col);
|
||||
m_buffers[m_buffer_index].remove(--m_buffer_col);
|
||||
printf("\b\e[s%s \e[u", m_buffers[m_buffer_index].data() + m_buffer_col);
|
||||
fflush(stdout);
|
||||
}
|
||||
else switch (ch)
|
||||
{
|
||||
case '\e':
|
||||
{
|
||||
|
@ -680,6 +690,8 @@ Input::Input()
|
|||
s_raw_termios.c_lflag &= ~(ECHO | ICANON);
|
||||
atexit([] { tcsetattr(0, TCSANOW, &s_original_termios); });
|
||||
s_termios_initialized = true;
|
||||
|
||||
m_backspace = s_original_termios.c_cc[VERASE];
|
||||
}
|
||||
|
||||
char hostname_buffer[HOST_NAME_MAX];
|
||||
|
|
|
@ -31,5 +31,7 @@ private:
|
|||
BAN::Optional<BAN::Vector<BAN::String>> m_tab_completions;
|
||||
size_t m_tab_completion_keep { 0 };
|
||||
|
||||
char m_backspace;
|
||||
|
||||
int m_waiting_utf8 { 0 };
|
||||
};
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(nologin ${SOURCES})
|
||||
banan_link_library(nologin ban)
|
||||
banan_link_library(nologin libc)
|
||||
|
||||
install(TARGETS nologin OPTIONAL)
|
|
@ -0,0 +1,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("This account is currently not available.\n");
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue