#pragma once #include #include namespace Kernel { class PseudoTerminalSlave; class PseudoTerminalMaster final : public CharacterDevice, public BAN::Weakable { public: static BAN::ErrorOr> create(mode_t, uid_t, gid_t); dev_t rdev() const override { return m_rdev; } BAN::StringView name() const override { return ""_sv; } BAN::ErrorOr> slave(); BAN::ErrorOr ptsname(); bool putchar(uint8_t ch); protected: BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; BAN::ErrorOr 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; } bool has_hungup_impl() const override { return !m_slave.valid(); } BAN::ErrorOr ioctl_impl(int, void*) override; private: PseudoTerminalMaster(BAN::UniqPtr, mode_t, uid_t, gid_t); ~PseudoTerminalMaster(); private: BAN::WeakPtr m_slave; mutable SpinLock m_buffer_lock; ThreadBlocker m_buffer_blocker; BAN::UniqPtr m_buffer; size_t m_buffer_tail { 0 }; size_t m_buffer_size { 0 }; const dev_t m_rdev; friend class BAN::RefPtr; }; class PseudoTerminalSlave final : public TTY, public BAN::Weakable { public: 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: bool putchar_impl(uint8_t ch) override; bool has_hungup_impl() const override { return !m_master.valid(); } BAN::ErrorOr ioctl_impl(int, void*) override; private: PseudoTerminalSlave(BAN::String&& name, uint32_t number, mode_t, uid_t, gid_t); ~PseudoTerminalSlave(); private: const BAN::String m_name; const uint32_t m_number; BAN::WeakPtr m_master; uint32_t m_width { 0 }; uint32_t m_height { 0 }; friend class PseudoTerminalMaster; friend class BAN::RefPtr; }; }