LibC/Kernel: Cleanup termios code
This is still not correct, but much better than it used to be
This commit is contained in:
parent
9bc02c81f8
commit
681d8327f5
|
@ -68,8 +68,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_exit(int status);
|
BAN::ErrorOr<long> sys_exit(int status);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_gettermios(::termios*);
|
BAN::ErrorOr<long> sys_tcgetattr(int fildes, termios*);
|
||||||
BAN::ErrorOr<long> sys_settermios(const ::termios*);
|
BAN::ErrorOr<long> sys_tcsetattr(int fildes, int optional_actions, const termios*);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
BAN::ErrorOr<long> sys_fork(uintptr_t rsp, uintptr_t rip);
|
||||||
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
BAN::ErrorOr<long> sys_exec(const char* path, const char* const* argv, const char* const* envp);
|
||||||
|
|
|
@ -4,18 +4,17 @@
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/Lock/SpinLock.h>
|
#include <kernel/Lock/SpinLock.h>
|
||||||
#include <kernel/Terminal/TerminalDriver.h>
|
#include <kernel/Terminal/TerminalDriver.h>
|
||||||
#include <kernel/Terminal/termios.h>
|
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
#include <LibInput/KeyEvent.h>
|
#include <LibInput/KeyEvent.h>
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class TTY : public CharacterDevice
|
class TTY : public CharacterDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void set_termios(const termios& termios) { m_termios = termios; }
|
|
||||||
termios get_termios() const { return m_termios; }
|
|
||||||
virtual void set_font(const LibFont::Font&) {};
|
virtual void set_font(const LibFont::Font&) {};
|
||||||
|
|
||||||
void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; }
|
void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; }
|
||||||
|
@ -33,6 +32,10 @@ namespace Kernel
|
||||||
void on_key_event(LibInput::KeyEvent);
|
void on_key_event(LibInput::KeyEvent);
|
||||||
void handle_input_byte(uint8_t);
|
void handle_input_byte(uint8_t);
|
||||||
|
|
||||||
|
void get_termios(termios* termios) { *termios = m_termios; }
|
||||||
|
// FIXME: validate termios
|
||||||
|
BAN::ErrorOr<void> set_termios(const termios* termios) { m_termios = *termios; return {}; }
|
||||||
|
|
||||||
virtual bool is_tty() const override { return true; }
|
virtual bool is_tty() const override { return true; }
|
||||||
|
|
||||||
virtual uint32_t height() const = 0;
|
virtual uint32_t height() const = 0;
|
||||||
|
@ -53,7 +56,15 @@ namespace Kernel
|
||||||
protected:
|
protected:
|
||||||
TTY(mode_t mode, uid_t uid, gid_t gid)
|
TTY(mode_t mode, uid_t uid, gid_t gid)
|
||||||
: CharacterDevice(mode, uid, gid)
|
: CharacterDevice(mode, uid, gid)
|
||||||
{ }
|
{
|
||||||
|
// FIXME: add correct baud and flags
|
||||||
|
m_termios.c_iflag = 0;
|
||||||
|
m_termios.c_oflag = 0;
|
||||||
|
m_termios.c_cflag = CS8;
|
||||||
|
m_termios.c_lflag = ECHO | ICANON;
|
||||||
|
m_termios.c_ospeed = B38400;
|
||||||
|
m_termios.c_ispeed = B38400;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void putchar_impl(uint8_t ch) = 0;
|
virtual void putchar_impl(uint8_t ch) = 0;
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/Terminal/TerminalDriver.h>
|
#include <kernel/Terminal/TerminalDriver.h>
|
||||||
#include <kernel/Terminal/termios.h>
|
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/ThreadBlocker.h>
|
#include <kernel/ThreadBlocker.h>
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
struct termios
|
|
||||||
{
|
|
||||||
bool canonical { true };
|
|
||||||
bool echo { true };
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -332,39 +332,38 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_gettermios(::termios* termios)
|
BAN::ErrorOr<long> Process::sys_tcgetattr(int fildes, termios* termios)
|
||||||
{
|
{
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
TRY(validate_pointer_access(termios, sizeof(::termios)));
|
TRY(validate_pointer_access(termios, sizeof(termios)));
|
||||||
|
|
||||||
if (!m_controlling_terminal)
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
|
if (!inode->is_tty())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
Kernel::termios ktermios = m_controlling_terminal->get_termios();
|
static_cast<TTY*>(inode.ptr())->get_termios(termios);
|
||||||
termios->c_lflag = 0;
|
|
||||||
if (ktermios.canonical)
|
|
||||||
termios->c_lflag |= ICANON;
|
|
||||||
if (ktermios.echo)
|
|
||||||
termios->c_lflag |= ECHO;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_settermios(const ::termios* termios)
|
BAN::ErrorOr<long> Process::sys_tcsetattr(int fildes, int optional_actions, const termios* termios)
|
||||||
{
|
{
|
||||||
|
if (optional_actions != TCSANOW)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
||||||
TRY(validate_pointer_access(termios, sizeof(::termios)));
|
TRY(validate_pointer_access(termios, sizeof(termios)));
|
||||||
|
|
||||||
if (!m_controlling_terminal)
|
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
|
||||||
|
if (!inode->is_tty())
|
||||||
return BAN::Error::from_errno(ENOTTY);
|
return BAN::Error::from_errno(ENOTTY);
|
||||||
|
|
||||||
Kernel::termios ktermios;
|
TRY(static_cast<TTY*>(inode.ptr())->set_termios(termios));
|
||||||
ktermios.echo = termios->c_lflag & ECHO;
|
|
||||||
ktermios.canonical = termios->c_lflag & ICANON;
|
// FIXME: SIGTTOU
|
||||||
|
|
||||||
m_controlling_terminal->set_termios(ktermios);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ^D + canonical
|
// ^D + canonical
|
||||||
if (ch == '\x04' && m_termios.canonical)
|
if (ch == '\x04' && (m_termios.c_lflag & ICANON))
|
||||||
{
|
{
|
||||||
m_output.flush = true;
|
m_output.flush = true;
|
||||||
m_output.thread_blocker.unblock();
|
m_output.thread_blocker.unblock();
|
||||||
|
@ -242,7 +242,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
// backspace + canonical
|
// backspace + canonical
|
||||||
if (ch == '\b' && m_termios.canonical)
|
if (ch == '\b' && (m_termios.c_lflag & ICANON))
|
||||||
{
|
{
|
||||||
do_backspace();
|
do_backspace();
|
||||||
return;
|
return;
|
||||||
|
@ -250,7 +250,7 @@ namespace Kernel
|
||||||
|
|
||||||
m_output.buffer[m_output.bytes++] = ch;
|
m_output.buffer[m_output.bytes++] = ch;
|
||||||
|
|
||||||
if (m_termios.echo)
|
if (m_termios.c_lflag & ECHO)
|
||||||
{
|
{
|
||||||
if ((ch <= 31 || ch == 127) && ch != '\n')
|
if ((ch <= 31 || ch == 127) && ch != '\n')
|
||||||
{
|
{
|
||||||
|
@ -276,7 +276,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == '\n' || !m_termios.canonical)
|
if (ch == '\n' || !(m_termios.c_lflag & ICANON))
|
||||||
{
|
{
|
||||||
m_output.flush = true;
|
m_output.flush = true;
|
||||||
m_output.thread_blocker.unblock();
|
m_output.thread_blocker.unblock();
|
||||||
|
|
|
@ -15,8 +15,8 @@ __BEGIN_DECLS
|
||||||
O(SYS_OPENAT, openat) \
|
O(SYS_OPENAT, openat) \
|
||||||
O(SYS_SEEK, seek) \
|
O(SYS_SEEK, seek) \
|
||||||
O(SYS_TELL, tell) \
|
O(SYS_TELL, tell) \
|
||||||
O(SYS_GET_TERMIOS, gettermios) \
|
O(SYS_TCGETATTR, tcgetattr) \
|
||||||
O(SYS_SET_TERMIOS, settermios) \
|
O(SYS_TCSETATTR, tcsetattr) \
|
||||||
O(SYS_FORK, fork) \
|
O(SYS_FORK, fork) \
|
||||||
O(SYS_EXEC, exec) \
|
O(SYS_EXEC, exec) \
|
||||||
O(SYS_SLEEP, sleep) \
|
O(SYS_SLEEP, sleep) \
|
||||||
|
|
|
@ -35,6 +35,8 @@ struct termios
|
||||||
tcflag_t c_cflag; /* Control modes. */
|
tcflag_t c_cflag; /* Control modes. */
|
||||||
tcflag_t c_lflag; /* Local modes. */
|
tcflag_t c_lflag; /* Local modes. */
|
||||||
cc_t c_cc[NCCS]; /* Control characters. */
|
cc_t c_cc[NCCS]; /* Control characters. */
|
||||||
|
speed_t c_ospeed;
|
||||||
|
speed_t c_ispeed;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BRKINT 0x001
|
#define BRKINT 0x001
|
||||||
|
|
|
@ -1,14 +1,65 @@
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
speed_t cfgetispeed(const struct termios*);
|
speed_t cfgetispeed(const struct termios* termios)
|
||||||
|
{
|
||||||
|
return termios->c_ispeed;
|
||||||
|
}
|
||||||
|
|
||||||
speed_t cfgetospeed(const struct termios*);
|
speed_t cfgetospeed(const struct termios* termios)
|
||||||
|
{
|
||||||
|
return termios->c_ospeed;
|
||||||
|
}
|
||||||
|
|
||||||
int cfsetispeed(struct termios*, speed_t);
|
static bool is_valid_speed(speed_t speed)
|
||||||
|
{
|
||||||
|
switch (speed)
|
||||||
|
{
|
||||||
|
case B0:
|
||||||
|
case B50:
|
||||||
|
case B75:
|
||||||
|
case B110:
|
||||||
|
case B134:
|
||||||
|
case B150:
|
||||||
|
case B200:
|
||||||
|
case B300:
|
||||||
|
case B600:
|
||||||
|
case B1200:
|
||||||
|
case B1800:
|
||||||
|
case B2400:
|
||||||
|
case B4800:
|
||||||
|
case B9600:
|
||||||
|
case B19200:
|
||||||
|
case B38400:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int cfsetospeed(struct termios*, speed_t);
|
int cfsetispeed(struct termios* termios, speed_t speed)
|
||||||
|
{
|
||||||
|
if (!is_valid_speed(speed))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
termios->c_ispeed = speed;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cfsetospeed(struct termios* termios, speed_t speed)
|
||||||
|
{
|
||||||
|
if (!is_valid_speed(speed))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
termios->c_ospeed = speed;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int tcdrain(int);
|
int tcdrain(int);
|
||||||
|
|
||||||
|
@ -16,16 +67,16 @@ int tcflow(int, int);
|
||||||
|
|
||||||
int tcflush(int, int);
|
int tcflush(int, int);
|
||||||
|
|
||||||
int tcgetattr(int, struct termios* termios)
|
int tcgetattr(int fildes, struct termios* termios)
|
||||||
{
|
{
|
||||||
return syscall(SYS_GET_TERMIOS, termios);
|
return syscall(SYS_TCGETATTR, fildes, termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t tcgetsid(int);
|
pid_t tcgetsid(int);
|
||||||
|
|
||||||
int tcsendbreak(int, int);
|
int tcsendbreak(int, int);
|
||||||
|
|
||||||
int tcsetattr(int, int, const struct termios* termios)
|
int tcsetattr(int fildes, int optional_actions, const struct termios* termios)
|
||||||
{
|
{
|
||||||
return syscall(SYS_SET_TERMIOS, termios);
|
return syscall(SYS_TCSETATTR, fildes, optional_actions, termios);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue