serenity/Kernel/TTY/SlavePTY.cpp

118 lines
2.8 KiB
C++

/*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Singleton.h>
#include <Kernel/Debug.h>
#include <Kernel/Process.h>
#include <Kernel/TTY/MasterPTY.h>
#include <Kernel/TTY/SlavePTY.h>
namespace Kernel {
static Singleton<SpinlockProtected<SlavePTY::List>> s_all_instances;
SpinlockProtected<SlavePTY::List>& SlavePTY::all_instances()
{
return s_all_instances;
}
bool SlavePTY::unref() const
{
bool did_hit_zero = SlavePTY::all_instances().with([&](auto&) {
if (deref_base())
return false;
m_list_node.remove();
const_cast<SlavePTY&>(*this).revoke_weak_ptrs();
return true;
});
if (did_hit_zero) {
const_cast<SlavePTY&>(*this).will_be_destroyed();
delete this;
}
return did_hit_zero;
}
SlavePTY::SlavePTY(MasterPTY& master, unsigned index)
: TTY(201, index)
, m_master(master)
, m_index(index)
{
auto& process = Process::current();
auto credentials = process.credentials();
set_uid(credentials->uid());
set_gid(credentials->gid());
set_size(80, 25);
SlavePTY::all_instances().with([&](auto& list) { list.append(*this); });
}
SlavePTY::~SlavePTY()
{
dbgln_if(SLAVEPTY_DEBUG, "~SlavePTY({})", m_index);
}
ErrorOr<NonnullOwnPtr<KString>> SlavePTY::pseudo_name() const
{
return KString::formatted("pts:{}", m_index);
}
void SlavePTY::echo(u8 ch)
{
if (should_echo_input()) {
auto buffer = UserOrKernelBuffer::for_kernel_buffer(&ch);
[[maybe_unused]] auto result = m_master->on_slave_write(buffer, 1);
}
}
void SlavePTY::on_master_write(UserOrKernelBuffer const& buffer, size_t size)
{
auto result = buffer.read_buffered<128>(size, [&](ReadonlyBytes data) {
for (const auto& byte : data)
emit(byte, false);
return data.size();
});
if (!result.is_error())
evaluate_block_conditions();
}
ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size)
{
m_time_of_last_write = kgettimeofday().to_truncated_seconds();
return m_master->on_slave_write(data, size);
}
bool SlavePTY::can_write(OpenFileDescription const&, u64) const
{
return m_master->can_write_from_slave();
}
bool SlavePTY::can_read(OpenFileDescription const& description, u64 offset) const
{
if (m_master->is_closed())
return true;
return TTY::can_read(description, offset);
}
ErrorOr<size_t> SlavePTY::read(OpenFileDescription& description, u64 offset, UserOrKernelBuffer& buffer, size_t size)
{
if (m_master->is_closed())
return 0;
return TTY::read(description, offset, buffer, size);
}
ErrorOr<void> SlavePTY::close()
{
m_master->notify_slave_closed({});
return {};
}
FileBlockerSet& SlavePTY::blocker_set()
{
return m_master->blocker_set();
}
}