Serenity Operating System
at master 117 lines 2.9 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Singleton.h> 8#include <Kernel/Debug.h> 9#include <Kernel/Process.h> 10#include <Kernel/TTY/MasterPTY.h> 11#include <Kernel/TTY/SlavePTY.h> 12 13namespace Kernel { 14 15static Singleton<SpinlockProtected<SlavePTY::List, LockRank::None>> s_all_instances; 16 17SpinlockProtected<SlavePTY::List, LockRank::None>& SlavePTY::all_instances() 18{ 19 return s_all_instances; 20} 21 22bool SlavePTY::unref() const 23{ 24 bool did_hit_zero = SlavePTY::all_instances().with([&](auto&) { 25 if (deref_base()) 26 return false; 27 m_list_node.remove(); 28 const_cast<SlavePTY&>(*this).revoke_weak_ptrs(); 29 return true; 30 }); 31 if (did_hit_zero) { 32 const_cast<SlavePTY&>(*this).will_be_destroyed(); 33 delete this; 34 } 35 return did_hit_zero; 36} 37 38SlavePTY::SlavePTY(MasterPTY& master, unsigned index) 39 : TTY(201, index) 40 , m_master(master) 41 , m_index(index) 42{ 43 auto& process = Process::current(); 44 auto credentials = process.credentials(); 45 set_uid(credentials->uid()); 46 set_gid(credentials->gid()); 47 set_size(80, 25); 48 49 SlavePTY::all_instances().with([&](auto& list) { list.append(*this); }); 50} 51 52SlavePTY::~SlavePTY() 53{ 54 dbgln_if(SLAVEPTY_DEBUG, "~SlavePTY({})", m_index); 55} 56 57ErrorOr<NonnullOwnPtr<KString>> SlavePTY::pseudo_name() const 58{ 59 return KString::formatted("pts:{}", m_index); 60} 61 62void SlavePTY::echo(u8 ch) 63{ 64 if (should_echo_input()) { 65 auto buffer = UserOrKernelBuffer::for_kernel_buffer(&ch); 66 [[maybe_unused]] auto result = m_master->on_slave_write(buffer, 1); 67 } 68} 69 70void SlavePTY::on_master_write(UserOrKernelBuffer const& buffer, size_t size) 71{ 72 auto result = buffer.read_buffered<128>(size, [&](ReadonlyBytes data) { 73 for (const auto& byte : data) 74 emit(byte, false); 75 return data.size(); 76 }); 77 if (!result.is_error()) 78 evaluate_block_conditions(); 79} 80 81ErrorOr<size_t> SlavePTY::on_tty_write(UserOrKernelBuffer const& data, size_t size) 82{ 83 m_time_of_last_write = kgettimeofday().to_truncated_seconds(); 84 return m_master->on_slave_write(data, size); 85} 86 87bool SlavePTY::can_write(OpenFileDescription const&, u64) const 88{ 89 return m_master->can_write_from_slave(); 90} 91 92bool SlavePTY::can_read(OpenFileDescription const& description, u64 offset) const 93{ 94 if (m_master->is_closed()) 95 return true; 96 return TTY::can_read(description, offset); 97} 98 99ErrorOr<size_t> SlavePTY::read(OpenFileDescription& description, u64 offset, UserOrKernelBuffer& buffer, size_t size) 100{ 101 if (m_master->is_closed()) 102 return 0; 103 return TTY::read(description, offset, buffer, size); 104} 105 106ErrorOr<void> SlavePTY::close() 107{ 108 m_master->notify_slave_closed({}); 109 return {}; 110} 111 112FileBlockerSet& SlavePTY::blocker_set() 113{ 114 return m_master->blocker_set(); 115} 116 117}