MasterPTY.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. KResultOr<NonnullRefPtr<MasterPTY>> MasterPTY::try_create(unsigned int index)
  17. {
  18. auto buffer = TRY(DoubleBuffer::try_create());
  19. auto master_pty = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) MasterPTY(index, move(buffer))));
  20. auto slave_pty = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) SlavePTY(*master_pty, index)));
  21. master_pty->m_slave = slave_pty;
  22. return master_pty;
  23. }
  24. MasterPTY::MasterPTY(unsigned index, NonnullOwnPtr<DoubleBuffer> buffer)
  25. : CharacterDevice(200, index)
  26. , m_index(index)
  27. , m_buffer(move(buffer))
  28. {
  29. m_pts_name = String::formatted("/dev/pts/{}", m_index);
  30. auto& process = Process::current();
  31. set_uid(process.uid());
  32. set_gid(process.gid());
  33. m_buffer->set_unblock_callback([this]() {
  34. if (m_slave)
  35. evaluate_block_conditions();
  36. });
  37. }
  38. MasterPTY::~MasterPTY()
  39. {
  40. dbgln_if(MASTERPTY_DEBUG, "~MasterPTY({})", m_index);
  41. PTYMultiplexer::the().notify_master_destroyed({}, m_index);
  42. }
  43. String MasterPTY::pts_name() const
  44. {
  45. return m_pts_name;
  46. }
  47. KResultOr<size_t> MasterPTY::read(OpenFileDescription&, u64, UserOrKernelBuffer& buffer, size_t size)
  48. {
  49. if (!m_slave && m_buffer->is_empty())
  50. return 0;
  51. return m_buffer->read(buffer, size);
  52. }
  53. KResultOr<size_t> MasterPTY::write(OpenFileDescription&, u64, const UserOrKernelBuffer& buffer, size_t size)
  54. {
  55. if (!m_slave)
  56. return EIO;
  57. m_slave->on_master_write(buffer, size);
  58. return size;
  59. }
  60. bool MasterPTY::can_read(const OpenFileDescription&, size_t) const
  61. {
  62. if (!m_slave)
  63. return true;
  64. return !m_buffer->is_empty();
  65. }
  66. bool MasterPTY::can_write(const OpenFileDescription&, size_t) const
  67. {
  68. return true;
  69. }
  70. void MasterPTY::notify_slave_closed(Badge<SlavePTY>)
  71. {
  72. dbgln_if(MASTERPTY_DEBUG, "MasterPTY({}): slave closed, my retains: {}, slave retains: {}", m_index, ref_count(), m_slave->ref_count());
  73. // +1 ref for my MasterPTY::m_slave
  74. // +1 ref for OpenFileDescription::m_device
  75. if (m_slave->ref_count() == 2)
  76. m_slave = nullptr;
  77. }
  78. KResultOr<size_t> MasterPTY::on_slave_write(const UserOrKernelBuffer& data, size_t size)
  79. {
  80. if (m_closed)
  81. return EIO;
  82. return m_buffer->write(data, size);
  83. }
  84. bool MasterPTY::can_write_from_slave() const
  85. {
  86. if (m_closed)
  87. return true;
  88. return m_buffer->space_for_writing();
  89. }
  90. KResult MasterPTY::close()
  91. {
  92. InterruptDisabler disabler;
  93. // After the closing OpenFileDescription dies, slave is the only thing keeping me alive.
  94. // From this point, let's consider ourselves closed.
  95. m_closed = true;
  96. if (m_slave)
  97. m_slave->hang_up();
  98. return KSuccess;
  99. }
  100. KResult MasterPTY::ioctl(OpenFileDescription& description, unsigned request, Userspace<void*> arg)
  101. {
  102. REQUIRE_PROMISE(tty);
  103. if (!m_slave)
  104. return EIO;
  105. if (request == TIOCSWINSZ || request == TIOCGPGRP)
  106. return m_slave->ioctl(description, request, arg);
  107. return EINVAL;
  108. }
  109. String MasterPTY::absolute_path(const OpenFileDescription&) const
  110. {
  111. return String::formatted("ptm:{}", m_pts_name);
  112. }
  113. String MasterPTY::device_name() const
  114. {
  115. return String::formatted("{}", minor());
  116. }
  117. }