diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index f25ee6b9..a5c278a7 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -59,6 +59,8 @@ namespace Kernel BAN::ErrorOr working_directory() const; BAN::ErrorOr set_working_directory(BAN::StringView); + TTY& tty() { ASSERT(m_tty); return *m_tty; } + BAN::ErrorOr allocate(size_t); void free(void*); diff --git a/kernel/include/kernel/Syscall.h b/kernel/include/kernel/Syscall.h index c3792c5d..1dba6d1c 100644 --- a/kernel/include/kernel/Syscall.h +++ b/kernel/include/kernel/Syscall.h @@ -10,6 +10,8 @@ #define SYS_FREE 8 #define SYS_SEEK 9 #define SYS_TELL 10 +#define SYS_GET_TERMIOS 11 +#define SYS_SET_TERMIOS 12 #include #include diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index d14a3a15..0747e0e4 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -8,7 +8,6 @@ #include #include - namespace Kernel { @@ -17,7 +16,8 @@ namespace Kernel public: TTY(TerminalDriver*); - void set_termios(const termios& termios) { m_termios = termios; } + void set_termios(const termios& termios) { m_termios = termios; } + termios get_termios() const { return m_termios; } void set_font(const Kernel::Font&); uint32_t height() const { return m_height; } diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 5c7e106f..483bf33e 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -2,6 +2,8 @@ #include #include +#include + namespace Kernel { @@ -76,6 +78,26 @@ namespace Kernel return res.value(); } + long sys_get_termios(::termios* termios) + { + auto current = Process::current().tty().get_termios(); + memset(termios, 0, sizeof(::termios)); + if (current.canonical) + termios->c_lflag |= ICANON; + if (current.echo) + termios->c_lflag |= ECHO; + return 0; + } + + long sys_set_termios(const ::termios* termios) + { + Kernel::termios new_termios; + new_termios.canonical = termios->c_lflag & ICANON; + new_termios.echo = termios->c_lflag & ECHO; + Process::current().tty().set_termios(new_termios); + return 0; + } + extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5) { Thread::current().set_in_syscall(true); @@ -121,6 +143,12 @@ namespace Kernel case SYS_TELL: ret = sys_tell((int)arg1); break; + case SYS_GET_TERMIOS: + ret = sys_get_termios((::termios*)arg1); + break; + case SYS_SET_TERMIOS: + ret = sys_set_termios((const ::termios*)arg1); + break; default: Kernel::panic("Unknown syscall {}", syscall); } diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index eec2e7ed..5fd9faba 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -9,6 +9,7 @@ set(LIBC_SOURCES stdio.cpp stdlib.cpp string.cpp + termios.cpp unistd.cpp math.S ) diff --git a/libc/include/termios.h b/libc/include/termios.h new file mode 100644 index 00000000..6def9609 --- /dev/null +++ b/libc/include/termios.h @@ -0,0 +1,120 @@ +#pragma once + +#include +#include + +#define NCCS 0 + +// c_iflag +#define BRKINT 0x001 +#define ICRNL 0x002 +#define IGNBRK 0x004 +#define IGNCR 0x008 +#define IGNPAR 0x010 +#define INLCR 0x020 +#define INPCK 0x040 +#define ISTRIP 0x080 +#define IXANY 0x100 +#define IXOFF 0x200 +#define IXON 0x400 +#define PARMRK 0x800 + +// c_oflag +#define OPOST 0x0001 +#define ONLCR 0x0002 +#define OCRNL 0x0004 +#define ONOCR 0x0008 +#define ONLRET 0x0010 +#define OFDEL 0x0020 +#define OFILL 0x0040 +#define NLDLY 0x0080 + #define NL0 0 + #define NL1 1 +#define CRDLY 0x0100 + #define CR0 0 + #define CR1 1 + #define CR2 2 + #define CR3 3 +#define TABDLY 0x0200 + #define TAB0 0 + #define TAB1 1 + #define TAB2 2 + #define TAB3 3 +#define BSDLY 0x0400 + #define BS0 0 + #define BS1 1 +#define VTDLY 0x0800 + #define VT0 0 + #define VT1 1 +#define FFDLY 0x1000 + #define FF0 0 + #define FF1 1 + +// c_cflag +#define CSIZE 0x01 + #define CS5 5 + #define CS6 6 + #define CS7 7 + #define CS8 8 +#define CSTOPB 0x02 +#define CREAD 0x04 +#define PARENB 0x08 +#define PARODD 0x10 +#define HUPCL 0x20 +#define CLOCAL 0x40 + +// c_lflag +#define ECHO 0x001 +#define ECHOE 0x002 +#define ECHOK 0x004 +#define ECHONL 0x008 +#define ICANON 0x010 +#define IEXTEN 0x020 +#define ISIG 0x040 +#define NOFLSH 0x080 +#define TOSTOP 0x100 + +// for tcsetattr +#define TCSANOW 1 +#define TCSADRAIN 2 +#define TCSAFLUSH 3 + +// for tcflush +#define TCIFLUSH 0x01 +#define TCIOFLUSH (TCIFLUSH | TCOFLUSH) +#define TCOFLUSH 0x02 + +// for tcflow +#define TCIOFF 1 +#define TCION 2 +#define TCOOFF 3 +#define TCOON 4 + +__BEGIN_DECLS + +typedef int cc_t; +typedef int speed_t; +typedef int tcflag_t; + +struct termios +{ + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_cc[NCCS]; +}; + +speed_t cfgetispeed(const struct termios*); +speed_t cfgetospeed(const struct termios*); +int cfsetispeed(struct termios*, speed_t); +int cfsetospeed(struct termios*, speed_t); +int tcdrain(int); +int tcflow(int, int); +int tcflush(int, int); +int tcgetattr(int, struct termios*); +pid_t tcgetsid(int); +int tcsendbreak(int, int); +int tcsetattr(int, int, const struct termios*); + +__END_DECLS diff --git a/libc/termios.cpp b/libc/termios.cpp new file mode 100644 index 00000000..26715a75 --- /dev/null +++ b/libc/termios.cpp @@ -0,0 +1,31 @@ +#include +#include +#include + +speed_t cfgetispeed(const struct termios*); + +speed_t cfgetospeed(const struct termios*); + +int cfsetispeed(struct termios*, speed_t); + +int cfsetospeed(struct termios*, speed_t); + +int tcdrain(int); + +int tcflow(int, int); + +int tcflush(int, int); + +int tcgetattr(int, struct termios* termios) +{ + return syscall(SYS_GET_TERMIOS, termios); +} + +pid_t tcgetsid(int); + +int tcsendbreak(int, int); + +int tcsetattr(int, int, const struct termios* termios) +{ + return syscall(SYS_SET_TERMIOS, termios); +} diff --git a/libc/unistd.cpp b/libc/unistd.cpp index 49104e1d..98236c31 100644 --- a/libc/unistd.cpp +++ b/libc/unistd.cpp @@ -90,6 +90,18 @@ long syscall(long syscall, ...) ret = Kernel::syscall(SYS_TELL, fd); break; } + case SYS_GET_TERMIOS: + { + struct termios* termios = va_arg(args, struct termios*); + ret = Kernel::syscall(SYS_GET_TERMIOS, (uintptr_t)termios); + break; + } + case SYS_SET_TERMIOS: + { + const struct termios* termios = va_arg(args, const struct termios*); + ret = Kernel::syscall(SYS_SET_TERMIOS, (uintptr_t)termios); + break; + } default: puts("LibC: Unhandeled syscall"); ret = -ENOSYS;