| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "lldb/Host/windows/ConnectionConPTYWindows.h" | |
| #include "lldb/Utility/Status.h" | |
| #include "lldb/Utility/Timeout.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| ConnectionConPTY::ConnectionConPTY(std::shared_ptr<PseudoConsole> pty) | |
| : ConnectionGenericFile(pty->GetSTDOUTHandle(), false), m_pty(pty) {} | |
| ConnectionConPTY::~ConnectionConPTY() = default; | |
| lldb::ConnectionStatus ConnectionConPTY::Connect(llvm::StringRef s, | |
| Status *error_ptr) { | |
| if (m_pty->IsConnected()) | |
| return eConnectionStatusSuccess; | |
| return eConnectionStatusNoConnection; | |
| } | |
| lldb::ConnectionStatus ConnectionConPTY::Disconnect(Status *error_ptr) { | |
| m_pty->Close(); | |
| return eConnectionStatusSuccess; | |
| } | |
| size_t ConnectionConPTY::Read(void *dst, size_t dst_len, | |
| const Timeout<std::micro> &timeout, | |
| lldb::ConnectionStatus &status, | |
| Status *error_ptr) { | |
| { | |
| std::unique_lock<std::mutex> guard(m_pty->GetMutex()); | |
| if (m_pty->IsStopping()) | |
| m_pty->GetCV().wait(guard, [this] { return !m_pty->IsStopping(); }); | |
| if (!m_pty->IsConnected()) { | |
| status = eConnectionStatusEndOfFile; | |
| return 0; | |
| } | |
| } | |
| char *out = static_cast<char *>(dst); | |
| size_t bytes_read = | |
| ConnectionGenericFile::Read(out, dst_len, timeout, status, error_ptr); | |
| if (bytes_read > 0) { | |
| StripConPTYSequences(out, bytes_read, !m_conpty_sequences_stripped); | |
| m_conpty_sequences_stripped = true; | |
| } | |
| return bytes_read; | |
| } | |
| size_t ConnectionConPTY::Write(const void *src, size_t src_len, | |
| lldb::ConnectionStatus &status, | |
| Status *error_ptr) { | |
| if (!m_pty || !m_pty->IsConnected()) { | |
| status = eConnectionStatusNoConnection; | |
| if (error_ptr) | |
| *error_ptr = Status::FromErrorString("ConPTY not connected"); | |
| return 0; | |
| } | |
| HANDLE stdin_handle = m_pty->GetSTDINHandle(); | |
| if (stdin_handle == INVALID_HANDLE_VALUE || stdin_handle == nullptr) { | |
| status = eConnectionStatusNoConnection; | |
| if (error_ptr) | |
| *error_ptr = Status::FromErrorString("ConPTY STDIN handle is invalid"); | |
| return 0; | |
| } | |
| DWORD written = 0; | |
| if (!::WriteFile(stdin_handle, src, static_cast<DWORD>(src_len), &written, | |
| nullptr)) { | |
| DWORD err = ::GetLastError(); | |
| status = (err == ERROR_BROKEN_PIPE || err == ERROR_NO_DATA) | |
| ? eConnectionStatusEndOfFile | |
| : eConnectionStatusError; | |
| if (error_ptr) | |
| *error_ptr = Status(err, lldb::eErrorTypeWin32); | |
| return written; | |
| } | |
| status = eConnectionStatusSuccess; | |
| return written; | |
| } |