MasterPTY.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Arch/x86/InterruptDisabler.h>
  7. #include <Kernel/Debug.h>
  8. #include <Kernel/Process.h>
  9. #include <Kernel/TTY/MasterPTY.h>
  10. #include <Kernel/TTY/PTYMultiplexer.h>
  11. #include <Kernel/TTY/SlavePTY.h>
  12. #include <LibC/errno_numbers.h>
  13. #include <LibC/signal_numbers.h>
  14. #include <LibC/sys/ioctl_numbers.h>
  15. namespace Kernel {
  16. RefPtr<MasterPTY> MasterPTY::try_create(unsigned int index)
  17. {
  18. auto buffer = DoubleBuffer::try_create();
  19. if (!buffer)
  20. return {};
  21. auto master_pty = adopt_ref_if_nonnull(new (nothrow) MasterPTY(index, buffer.release_nonnull()));
  22. if (!master_pty)
  23. return {};
  24. auto slave_pty = adopt_ref_if_nonnull(new (nothrow) SlavePTY(*master_pty, index));
  25. if (!slave_pty)
  26. return {};
  27. master_pty->m_slave = slave_pty;
  28. return master_pty;
  29. }
  30. MasterPTY::MasterPTY(unsigned index, NonnullOwnPtr<DoubleBuffer> buffer)
  31. : CharacterDevice(200, index)
  32. , m_index(index)
  33. , m_buffer(move(buffer))
  34. {
  35. m_pts_name = String::formatted("/dev/pts/{}", m_index);
  36. auto& process = Process::current();
  37. set_uid(process.uid());
  38. set_gid(process.gid());
  39. m_buffer->set_unblock_callback([this]() {
  40. if (m_slave)
  41. evaluate_block_conditions();
  42. });
  43. }
  44. MasterPTY::~MasterPTY()
  45. {
  46. dbgln_if(MASTERPTY_DEBUG, "~MasterPTY({})", m_index);
  47. PTYMultiplexer::the().notify_master_destroyed({}, m_index);
  48. }
  49. String MasterPTY::pts_name() const
  50. {
  51. return m_pts_name;
  52. }
  53. KResultOr<size_t> MasterPTY::read(FileDescription&, u64, UserOrKernelBuffer& buffer, size_t size)
  54. {
  55. if (!m_slave && m_buffer->is_empty())
  56. return 0;
  57. return m_buffer->read(buffer, size);
  58. }
  59. KResultOr<size_t> MasterPTY::write(FileDescription&, u64, const UserOrKernelBuffer& buffer, size_t size)
  60. {
  61. if (!m_slave)
  62. return EIO;
  63. m_slave->on_master_write(buffer, size);
  64. return size;
  65. }
  66. bool MasterPTY::can_read(const FileDescription&, size_t) const
  67. {
  68. if (!m_slave)
  69. return true;
  70. return !m_buffer->is_empty();
  71. }
  72. bool MasterPTY::can_write(const FileDescription&, size_t) const
  73. {
  74. return true;
  75. }
  76. void MasterPTY::notify_slave_closed(Badge<SlavePTY>)
  77. {
  78. dbgln_if(MASTERPTY_DEBUG, "MasterPTY({}): slave closed, my retains: {}, slave retains: {}", m_index, ref_count(), m_slave->ref_count());
  79. // +1 ref for my MasterPTY::m_slave
  80. // +1 ref for FileDescription::m_device
  81. if (m_slave->ref_count() == 2)
  82. m_slave = nullptr;
  83. }
  84. KResultOr<size_t> MasterPTY::on_slave_write(const UserOrKernelBuffer& data, size_t size)
  85. {
  86. if (m_closed)
  87. return EIO;
  88. return m_buffer->write(data, size);
  89. }
  90. bool MasterPTY::can_write_from_slave() const
  91. {
  92. if (m_closed)
  93. return true;
  94. return m_buffer->space_for_writing();
  95. }
  96. KResult MasterPTY::close()
  97. {
  98. InterruptDisabler disabler;
  99. // After the closing FileDescription dies, slave is the only thing keeping me alive.
  100. // From this point, let's consider ourselves closed.
  101. m_closed = true;
  102. if (m_slave)
  103. m_slave->hang_up();
  104. return KSuccess;
  105. }
  106. KResult MasterPTY::ioctl(FileDescription& description, unsigned request, Userspace<void*> arg)
  107. {
  108. REQUIRE_PROMISE(tty);
  109. if (!m_slave)
  110. return EIO;
  111. if (request == TIOCSWINSZ || request == TIOCGPGRP)
  112. return m_slave->ioctl(description, request, arg);
  113. return EINVAL;
  114. }
  115. String MasterPTY::absolute_path(const FileDescription&) const
  116. {
  117. return String::formatted("ptm:{}", m_pts_name);
  118. }
  119. String MasterPTY::device_name() const
  120. {
  121. return String::formatted("{}", minor());
  122. }
  123. }