SlavePTY.cpp 2.8 KB

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