LLDB mainline
ConnectionConPTYWindows.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "lldb/Utility/Status.h"
12
13#include <cstring>
14
15using namespace lldb;
16using namespace lldb_private;
17
18/// Remove ConPTY management sequences from a buffer in-place.
19///
20/// ConPTY injects several VT sequences into its output pipe that are not part
21/// of the inferior's output: a cursor-position query (\x1b[6n) emitted during
22/// PSEUDOCONSOLE_INHERIT_CURSOR initialisation, Win32 Input Mode toggles
23/// (\x1b[?9001h/l), focus-event toggles (\x1b[?1004h/l), and a window-title
24/// OSC sequence (\x1b]0;...\x07). These sequences must not reach the outer
25/// terminal.
26///
27/// \param[in,out] data Buffer containing raw ConPTY output.
28/// \param[in,out] len On entry, the number of valid bytes in \p data.
29/// Updated to the number of bytes after stripping.
30/// \param[in] strip_init If true, also strip init-only sequences (\x1b[m,
31/// \x1b[?25h) that ConPTY emits at startup.
32static void StripConPTYSequences(void *data, size_t &len, bool strip_init) {
33 auto *buf = static_cast<char *>(data);
34 char *out = buf;
35 const char *in = buf;
36 const char *end = buf + len;
37
38 while (in < end) {
39 if (*in != '\x1b') {
40 *out++ = *in++;
41 continue;
42 }
43
44 size_t remaining = end - in;
45
46 // \x1b[6n - cursor-position query (PSEUDOCONSOLE_INHERIT_CURSOR init)
47 // This query is always replied to in OpenPseudoConsole.
48 if (remaining >= 4 && memcmp(in, "\x1b[6n", 4) == 0) {
49 in += 4;
50 continue;
51 }
52
53 if (strip_init) {
54 // \x1b[m - SGR reset (ConPTY init)
55 if (remaining >= 3 && memcmp(in, "\x1b[m", 3) == 0) {
56 in += 3;
57 continue;
58 }
59
60 // \x1b[?25h - show cursor (ConPTY init)
61 if (remaining >= 6 && memcmp(in, "\x1b[?25h", 6) == 0) {
62 in += 6;
63 continue;
64 }
65 }
66
67 // \x1b[?9001h / \x1b[?9001l - Win32 Input Mode enable/disable
68 if (remaining >= 8 && memcmp(in, "\x1b[?9001", 7) == 0 &&
69 (in[7] == 'h' || in[7] == 'l')) {
70 in += 8;
71 continue;
72 }
73
74 // \x1b[?1004h / \x1b[?1004l - focus-event reporting enable/disable
75 if (remaining >= 8 && memcmp(in, "\x1b[?1004", 7) == 0 &&
76 (in[7] == 'h' || in[7] == 'l')) {
77 in += 8;
78 continue;
79 }
80
81 // \x1b]0;...\x07 - ConPTY window-title OSC sequence
82 if (remaining >= 4 && in[1] == ']' && in[2] == '0' && in[3] == ';') {
83 const char *bel =
84 static_cast<const char *>(memchr(in + 4, '\x07', end - in - 4));
85 // We assume a sequence is not split accross multiple chunks.
86 if (bel)
87 in = bel + 1;
88 else
89 in = end;
90 continue;
91 }
92
93 *out++ = *in++;
94 }
95
96 len = static_cast<size_t>(out - buf);
97}
98
99ConnectionConPTY::ConnectionConPTY(std::shared_ptr<PseudoConsole> pty)
100 : ConnectionGenericFile(pty->GetSTDOUTHandle(), false), m_pty(pty) {}
101
103
105 Status *error_ptr) {
106 if (m_pty->IsConnected())
109}
110
115
116size_t ConnectionConPTY::Read(void *dst, size_t dst_len,
117 const Timeout<std::micro> &timeout,
119 Status *error_ptr) {
120 {
121 std::unique_lock<std::mutex> guard(m_pty->GetMutex());
122 if (m_pty->IsStopping())
123 m_pty->GetCV().wait(guard, [this] { return !m_pty->IsStopping(); });
124 if (!m_pty->IsConnected()) {
126 return 0;
127 }
128 }
129
130 char *out = static_cast<char *>(dst);
131 size_t bytes_read =
132 ConnectionGenericFile::Read(out, dst_len, timeout, status, error_ptr);
133
134 if (bytes_read > 0) {
137 }
138
139 return bytes_read;
140}
141
142size_t ConnectionConPTY::Write(const void *src, size_t src_len,
144 Status *error_ptr) {
145 llvm_unreachable("not implemented");
146}
static void StripConPTYSequences(void *data, size_t &len, bool strip_init)
Remove ConPTY management sequences from a buffer in-place.
lldb::ConnectionStatus Disconnect(Status *error_ptr) override
Disconnect the communications connection if one is currently connected.
size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr) override
The actual write function that attempts to write to the communications protocol.
ConnectionConPTY(std::shared_ptr< PseudoConsole > pty)
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
Read from the ConPTY's pipe.
std::shared_ptr< PseudoConsole > m_pty
lldb::ConnectionStatus Connect(llvm::StringRef s, Status *error_ptr) override
Connect using the connect string url.
size_t Read(void *dst, size_t dst_len, const Timeout< std::micro > &timeout, lldb::ConnectionStatus &status, Status *error_ptr) override
The read function that attempts to read from the connection.
An error handling class.
Definition Status.h:118
A class that represents a running process on the host machine.
ConnectionStatus
Connection Status Types.
@ eConnectionStatusEndOfFile
End-of-file encountered.
@ eConnectionStatusSuccess
Success.
@ eConnectionStatusNoConnection
No connection.