11#include "lldb/Host/Config.h"
13#include "llvm/ADT/STLExtras.h"
19#if LLDB_ENABLE_TERMIOS
30#if LLDB_ENABLE_TERMIOS
31 struct termios m_termios;
37#if !LLDB_ENABLE_TERMIOS
39 return llvm::createStringError(llvm::inconvertibleErrorCode(),
40 "termios support missing in LLDB");
45#if LLDB_ENABLE_TERMIOS
47 return llvm::createStringError(llvm::inconvertibleErrorCode(),
51 return llvm::createStringError(llvm::inconvertibleErrorCode(),
55 if (::tcgetattr(
m_fd, &data.m_termios) != 0)
56 return llvm::createStringError(
57 std::error_code(errno, std::generic_category()),
58 "unable to get teletype attributes");
66#if LLDB_ENABLE_TERMIOS
70 if (::tcsetattr(
m_fd, TCSANOW, &data.m_termios) != 0)
71 return llvm::createStringError(
72 std::error_code(errno, std::generic_category()),
73 "unable to set teletype attributes");
74 return llvm::Error::success();
81#if LLDB_ENABLE_TERMIOS
82 llvm::Expected<Data> data =
GetData();
84 return data.takeError();
86 struct termios &fd_termios = data->m_termios;
87 fd_termios.c_lflag &= ~ECHO;
89 fd_termios.c_lflag |= ECHO;
97#if LLDB_ENABLE_TERMIOS
98 llvm::Expected<Data> data =
GetData();
100 return data.takeError();
102 struct termios &fd_termios = data->m_termios;
103 fd_termios.c_lflag &= ~ICANON;
105 fd_termios.c_lflag |= ICANON;
113#if LLDB_ENABLE_TERMIOS
114 llvm::Expected<Data> data =
GetData();
116 return data.takeError();
118 struct termios &fd_termios = data->m_termios;
119 ::cfmakeraw(&fd_termios);
123 fd_termios.c_cc[VMIN] = 1;
124 fd_termios.c_cc[VTIME] = 0;
132#if LLDB_ENABLE_TERMIOS
133static std::optional<speed_t> baudRateToConst(
unsigned int baud_rate) {
278#if LLDB_ENABLE_TERMIOS
279 llvm::Expected<Data> data =
GetData();
281 return data.takeError();
283 struct termios &fd_termios = data->m_termios;
284 std::optional<speed_t> val = baudRateToConst(baud_rate);
286 return llvm::createStringError(llvm::inconvertibleErrorCode(),
287 "baud rate %d unsupported by the platform",
289 if (::cfsetispeed(&fd_termios, *val) != 0)
290 return llvm::createStringError(
291 std::error_code(errno, std::generic_category()),
292 "setting input baud rate failed");
293 if (::cfsetospeed(&fd_termios, *val) != 0)
294 return llvm::createStringError(
295 std::error_code(errno, std::generic_category()),
296 "setting output baud rate failed");
304#if LLDB_ENABLE_TERMIOS
305 llvm::Expected<Data> data =
GetData();
307 return data.takeError();
309 struct termios &fd_termios = data->m_termios;
312 fd_termios.c_cflag &= ~CSTOPB;
315 fd_termios.c_cflag |= CSTOPB;
318 return llvm::createStringError(
319 llvm::inconvertibleErrorCode(),
320 "invalid stop bit count: %d (must be 1 or 2)", stop_bits);
329#if LLDB_ENABLE_TERMIOS
330 llvm::Expected<Data> data =
GetData();
332 return data.takeError();
334 struct termios &fd_termios = data->m_termios;
335 fd_termios.c_cflag &= ~(
342 fd_termios.c_cflag |= PARENB;
344 fd_termios.c_cflag |= PARODD;
347 fd_termios.c_cflag |= CMSPAR;
349 return llvm::createStringError(
350 llvm::inconvertibleErrorCode(),
351 "space/mark parity is not supported by the platform");
362#if LLDB_ENABLE_TERMIOS
363 llvm::Expected<Data> data =
GetData();
365 return data.takeError();
367 struct termios &fd_termios = data->m_termios;
368 fd_termios.c_iflag &= ~(IGNPAR | PARMRK | INPCK);
371 fd_termios.c_iflag |= INPCK;
373 fd_termios.c_iflag |= IGNPAR;
375 fd_termios.c_iflag |= PARMRK;
384#if LLDB_ENABLE_TERMIOS
385 llvm::Expected<Data> data =
GetData();
387 return data.takeError();
390 struct termios &fd_termios = data->m_termios;
391 fd_termios.c_cflag &= ~CRTSCTS;
393 fd_termios.c_cflag |= CRTSCTS;
397 return llvm::createStringError(
398 llvm::inconvertibleErrorCode(),
399 "hardware flow control is not supported by the platform");
400 return llvm::Error::success();
409 return ::GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == FILE_TYPE_CHAR;
411 static std::optional<bool> g_result;
413 return g_result.value();
415 const char *lang_var = std::getenv(
"LANG");
419 llvm::StringRef(lang_var).lower().find(
"utf-8") != std::string::npos;
420 return g_result.value();
426 Save(term, save_process_group);
441 if (
m_tty.IsATerminal()) {
443 int fd =
m_tty.GetFileDescriptor();
445#if LLDB_ENABLE_TERMIOS
447 if (::tcgetattr(fd, &new_data->m_termios) == 0)
448 m_data = std::move(new_data);
450 if (save_process_group)
460 const int fd =
m_tty.GetFileDescriptor();
464#if LLDB_ENABLE_TERMIOS
466 tcsetattr(fd, TCSANOW, &
m_data->m_termios);
471 void (*saved_sigttou_callback)(int) =
nullptr;
472 saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN);
476 signal(SIGTTOU, saved_sigttou_callback);
485 return m_tty.FileDescriptorIsValid() &&
static llvm::Error termiosMissingError()
~TerminalState()
Destroy the instance, restoring terminal state if saved.
int m_tflags
Cached tflags information.
bool TFlagsIsValid() const
Test if tflags is valid.
bool Save(Terminal term, bool save_process_group)
Save the TTY state for fd.
std::unique_ptr< Terminal::Data > m_data
Platform-specific implementation.
bool TTYStateIsValid() const
Test if ttystate is valid.
bool Restore() const
Restore the TTY state to the cached state.
Terminal m_tty
A terminal.
lldb::pid_t m_process_group
Cached process group information.
TerminalState(Terminal term=-1, bool save_process_group=false)
Construct a new instance and optionally save terminal state.
bool IsValid() const
Test for valid cached TTY state information.
bool ProcessGroupIsValid() const
Test if the process group information is valid.
llvm::Error SetEcho(bool enabled)
llvm::Error SetParityCheck(ParityCheck parity_check)
llvm::Error SetCanonical(bool enabled)
llvm::Error SetBaudRate(unsigned int baud_rate)
bool FileDescriptorIsValid() const
llvm::Error SetData(const Data &data)
llvm::Error SetHardwareFlowControl(bool enabled)
llvm::Expected< Data > GetData()
llvm::Error SetParity(Parity parity)
llvm::Error SetStopBits(unsigned int stop_bits)
static bool SupportsUnicode()
Returns whether or not the current terminal supports Unicode rendering.
A class that represents a running process on the host machine.