Kernel/LibC: Add initial pseudo terminal support
This patch implements posix_openpt() and ptsname() grantpt() and unlockpt() are left in LibC as stubs, as posix_openpt currently does all of the needed work.
This commit is contained in:
@@ -9,7 +9,7 @@ namespace Kernel
|
||||
{
|
||||
Framebuffer = 1,
|
||||
TTY,
|
||||
Serial,
|
||||
PTSMaster,
|
||||
Null,
|
||||
Zero,
|
||||
Debug,
|
||||
|
||||
@@ -174,6 +174,8 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<long> sys_ttyname(int fildes, char* storage);
|
||||
BAN::ErrorOr<long> sys_isatty(int fildes);
|
||||
BAN::ErrorOr<long> sys_posix_openpt(int flags);
|
||||
BAN::ErrorOr<long> sys_ptsname(int fildes, char* buffer, size_t buffer_len);
|
||||
|
||||
BAN::ErrorOr<long> sys_tty_ctrl(int fildes, int command, int flags);
|
||||
|
||||
|
||||
84
kernel/include/kernel/Terminal/PseudoTerminal.h
Normal file
84
kernel/include/kernel/Terminal/PseudoTerminal.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/WeakPtr.h>
|
||||
#include <kernel/Terminal/TTY.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class PseudoTerminalSlave;
|
||||
|
||||
class PseudoTerminalMaster final : public CharacterDevice, public BAN::Weakable<PseudoTerminalMaster>
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<PseudoTerminalMaster>> create(mode_t, uid_t, gid_t);
|
||||
|
||||
dev_t rdev() const override { return m_rdev; }
|
||||
BAN::StringView name() const override { return "<ptmx>"_sv; }
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<PseudoTerminalSlave>> slave();
|
||||
|
||||
BAN::ErrorOr<BAN::String> ptsname();
|
||||
|
||||
void putchar(uint8_t ch);
|
||||
|
||||
protected:
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
|
||||
bool can_read_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size > 0; }
|
||||
bool can_write_impl() const override { SpinLockGuard _(m_buffer_lock); return m_buffer_size < m_buffer->size(); }
|
||||
bool has_error_impl() const override { return false; }
|
||||
|
||||
private:
|
||||
PseudoTerminalMaster(BAN::UniqPtr<VirtualRange>, mode_t, uid_t, gid_t);
|
||||
~PseudoTerminalMaster();
|
||||
|
||||
private:
|
||||
BAN::WeakPtr<PseudoTerminalSlave> m_slave;
|
||||
|
||||
mutable SpinLock m_buffer_lock;
|
||||
ThreadBlocker m_buffer_blocker;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||
size_t m_buffer_tail { 0 };
|
||||
size_t m_buffer_size { 0 };
|
||||
|
||||
const dev_t m_rdev;
|
||||
|
||||
friend class BAN::RefPtr<PseudoTerminalMaster>;
|
||||
};
|
||||
|
||||
class PseudoTerminalSlave final : public TTY, public BAN::Weakable<PseudoTerminalSlave>
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<PseudoTerminalSlave>> create(BAN::String&& name, mode_t, uid_t, gid_t);
|
||||
|
||||
BAN::StringView name() const override { return m_name; }
|
||||
|
||||
uint32_t height() const override { return m_height; }
|
||||
uint32_t width() const override { return m_width; }
|
||||
|
||||
void clear() override;
|
||||
|
||||
protected:
|
||||
void putchar_impl(uint8_t ch) override;
|
||||
|
||||
private:
|
||||
PseudoTerminalSlave(BAN::UniqPtr<VirtualRange>, BAN::String&& name, mode_t, uid_t, gid_t);
|
||||
|
||||
private:
|
||||
BAN::String m_name;
|
||||
|
||||
BAN::WeakPtr<PseudoTerminalMaster> m_master;
|
||||
BAN::UniqPtr<VirtualRange> m_buffer;
|
||||
size_t m_buffer_tail { 0 };
|
||||
size_t m_buffer_size { 0 };
|
||||
|
||||
uint32_t m_width { 0 };
|
||||
uint32_t m_height { 0 };
|
||||
|
||||
friend class PseudoTerminalMaster;
|
||||
friend class BAN::RefPtr<PseudoTerminalSlave>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -63,11 +63,6 @@ namespace Kernel
|
||||
Serial m_serial;
|
||||
BAN::CircularQueue<uint8_t, 128> m_input;
|
||||
SpinLock m_input_lock;
|
||||
|
||||
public:
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Kernel
|
||||
virtual uint32_t width() const = 0;
|
||||
void putchar(uint8_t ch);
|
||||
|
||||
virtual dev_t rdev() const final override { return m_rdev; }
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
@@ -54,17 +56,7 @@ namespace Kernel
|
||||
virtual bool has_error_impl() const override { return false; }
|
||||
|
||||
protected:
|
||||
TTY(mode_t mode, uid_t uid, gid_t 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;
|
||||
}
|
||||
TTY(mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
virtual void putchar_impl(uint8_t ch) = 0;
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
@@ -79,6 +71,8 @@ namespace Kernel
|
||||
termios m_termios;
|
||||
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
|
||||
pid_t m_foreground_pgrp { 0 };
|
||||
|
||||
struct tty_ctrl_t
|
||||
|
||||
@@ -83,11 +83,6 @@ namespace Kernel
|
||||
bool m_show_cursor { true };
|
||||
|
||||
TerminalDriver* m_terminal_driver { nullptr };
|
||||
|
||||
public:
|
||||
virtual dev_t rdev() const override { return m_rdev; }
|
||||
private:
|
||||
const dev_t m_rdev;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user