2020-01-18 11:38:21 +03:00
|
|
|
/*
|
2021-08-16 23:13:58 +03:00
|
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
2020-01-18 11:38:21 +03:00
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2021-08-16 23:13:58 +03:00
|
|
|
#include <AK/Singleton.h>
|
2021-01-25 18:07:10 +03:00
|
|
|
#include <Kernel/Debug.h>
|
2019-04-03 13:25:24 +03:00
|
|
|
#include <Kernel/FileSystem/DevPtsFS.h>
|
2019-01-31 07:55:30 +03:00
|
|
|
#include <Kernel/Process.h>
|
2021-07-11 22:02:15 +03:00
|
|
|
#include <Kernel/TTY/MasterPTY.h>
|
|
|
|
#include <Kernel/TTY/SlavePTY.h>
|
2019-01-15 08:30:19 +03:00
|
|
|
|
2020-02-16 03:27:42 +03:00
|
|
|
namespace Kernel {
|
|
|
|
|
2021-08-22 02:37:17 +03:00
|
|
|
static Singleton<SpinlockProtected<SlavePTY::List>> s_all_instances;
|
2021-08-16 23:13:58 +03:00
|
|
|
|
2021-08-22 02:37:17 +03:00
|
|
|
SpinlockProtected<SlavePTY::List>& SlavePTY::all_instances()
|
2021-08-16 23:13:58 +03:00
|
|
|
{
|
|
|
|
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();
|
|
|
|
return true;
|
|
|
|
});
|
2021-09-10 14:44:46 +03:00
|
|
|
if (did_hit_zero) {
|
|
|
|
const_cast<SlavePTY&>(*this).before_removing();
|
2021-08-16 23:13:58 +03:00
|
|
|
delete this;
|
2021-09-10 14:44:46 +03:00
|
|
|
}
|
2021-08-16 23:13:58 +03:00
|
|
|
return did_hit_zero;
|
|
|
|
}
|
|
|
|
|
2019-01-16 04:11:50 +03:00
|
|
|
SlavePTY::SlavePTY(MasterPTY& master, unsigned index)
|
2019-12-09 23:03:39 +03:00
|
|
|
: TTY(201, index)
|
2019-01-16 04:11:50 +03:00
|
|
|
, m_master(master)
|
2019-01-15 08:30:19 +03:00
|
|
|
, m_index(index)
|
|
|
|
{
|
2021-02-17 18:37:11 +03:00
|
|
|
m_tty_name = String::formatted("/dev/pts/{}", m_index);
|
2021-08-19 22:45:07 +03:00
|
|
|
auto& process = Process::current();
|
|
|
|
set_uid(process.uid());
|
|
|
|
set_gid(process.gid());
|
2019-01-15 10:49:24 +03:00
|
|
|
set_size(80, 25);
|
2021-08-16 23:13:58 +03:00
|
|
|
|
|
|
|
SlavePTY::all_instances().with([&](auto& list) { list.append(*this); });
|
2019-01-15 08:30:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
SlavePTY::~SlavePTY()
|
|
|
|
{
|
2021-02-07 15:03:24 +03:00
|
|
|
dbgln_if(SLAVEPTY_DEBUG, "~SlavePTY({})", m_index);
|
2019-01-15 08:30:19 +03:00
|
|
|
}
|
|
|
|
|
2021-05-12 23:47:06 +03:00
|
|
|
String const& SlavePTY::tty_name() const
|
2019-01-15 08:30:19 +03:00
|
|
|
{
|
2019-04-16 01:35:02 +03:00
|
|
|
return m_tty_name;
|
2019-01-15 08:30:19 +03:00
|
|
|
}
|
|
|
|
|
2019-10-20 09:12:00 +03:00
|
|
|
void SlavePTY::echo(u8 ch)
|
|
|
|
{
|
|
|
|
if (should_echo_input()) {
|
2020-09-12 06:11:07 +03:00
|
|
|
auto buffer = UserOrKernelBuffer::for_kernel_buffer(&ch);
|
2021-06-16 16:20:35 +03:00
|
|
|
[[maybe_unused]] auto result = m_master->on_slave_write(buffer, 1);
|
2019-10-20 09:12:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 16:20:35 +03:00
|
|
|
void SlavePTY::on_master_write(const UserOrKernelBuffer& buffer, size_t size)
|
2019-01-15 08:30:19 +03:00
|
|
|
{
|
2021-09-01 09:44:55 +03:00
|
|
|
auto result = buffer.read_buffered<128>(size, [&](ReadonlyBytes data) {
|
|
|
|
for (const auto& byte : data)
|
|
|
|
emit(byte, false);
|
|
|
|
return data.size();
|
2020-09-12 06:11:07 +03:00
|
|
|
});
|
2021-05-13 10:08:44 +03:00
|
|
|
if (!result.is_error())
|
2020-11-30 02:05:27 +03:00
|
|
|
evaluate_block_conditions();
|
2019-01-15 08:30:19 +03:00
|
|
|
}
|
|
|
|
|
2021-06-16 16:20:35 +03:00
|
|
|
KResultOr<size_t> SlavePTY::on_tty_write(const UserOrKernelBuffer& data, size_t size)
|
2019-01-15 08:30:19 +03:00
|
|
|
{
|
2021-02-28 04:18:48 +03:00
|
|
|
m_time_of_last_write = kgettimeofday().to_truncated_seconds();
|
2019-02-05 15:09:01 +03:00
|
|
|
return m_master->on_slave_write(data, size);
|
2019-01-15 08:30:19 +03:00
|
|
|
}
|
2019-01-15 11:17:22 +03:00
|
|
|
|
2021-09-07 14:39:11 +03:00
|
|
|
bool SlavePTY::can_write(const OpenFileDescription&, size_t) const
|
2019-01-15 11:17:22 +03:00
|
|
|
{
|
2019-01-30 21:05:59 +03:00
|
|
|
return m_master->can_write_from_slave();
|
2019-01-15 11:17:22 +03:00
|
|
|
}
|
2019-01-30 20:26:19 +03:00
|
|
|
|
2021-09-07 14:39:11 +03:00
|
|
|
bool SlavePTY::can_read(const OpenFileDescription& description, size_t offset) const
|
2019-02-05 14:27:32 +03:00
|
|
|
{
|
|
|
|
if (m_master->is_closed())
|
|
|
|
return true;
|
2020-04-10 12:44:42 +03:00
|
|
|
return TTY::can_read(description, offset);
|
2019-02-05 14:27:32 +03:00
|
|
|
}
|
|
|
|
|
2021-09-07 14:39:11 +03:00
|
|
|
KResultOr<size_t> SlavePTY::read(OpenFileDescription& description, u64 offset, UserOrKernelBuffer& buffer, size_t size)
|
2019-02-05 14:27:32 +03:00
|
|
|
{
|
|
|
|
if (m_master->is_closed())
|
|
|
|
return 0;
|
2020-04-10 12:44:42 +03:00
|
|
|
return TTY::read(description, offset, buffer, size);
|
2019-02-05 14:27:32 +03:00
|
|
|
}
|
|
|
|
|
2020-06-02 19:20:05 +03:00
|
|
|
KResult SlavePTY::close()
|
2019-01-30 20:26:19 +03:00
|
|
|
{
|
2019-05-31 16:44:04 +03:00
|
|
|
m_master->notify_slave_closed({});
|
2020-06-02 19:20:05 +03:00
|
|
|
return KSuccess;
|
2019-01-30 20:26:19 +03:00
|
|
|
}
|
2020-02-16 03:27:42 +03:00
|
|
|
|
2021-08-22 16:59:47 +03:00
|
|
|
FileBlockerSet& SlavePTY::blocker_set()
|
2020-11-30 02:05:27 +03:00
|
|
|
{
|
2021-08-22 16:59:47 +03:00
|
|
|
return m_master->blocker_set();
|
2020-11-30 02:05:27 +03:00
|
|
|
}
|
|
|
|
|
2020-02-16 03:27:42 +03:00
|
|
|
}
|