1 //===-- Terminal.h ----------------------------------------------*- C++ -*-===//
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 
9 #ifndef LLDB_HOST_TERMINAL_H
10 #define LLDB_HOST_TERMINAL_H
11 
12 #include "lldb/lldb-private.h"
13 #include "llvm/Support/Error.h"
14 
15 namespace lldb_private {
16 
17 class TerminalState;
18 
19 class Terminal {
20 public:
21   enum class Parity {
22     No,
23     Even,
24     Odd,
25     Space,
26     Mark,
27   };
28 
29   enum class ParityCheck {
30     // No parity checking
31     No,
32     // Replace erraneous bytes with NUL
33     ReplaceWithNUL,
34     // Ignore erraneous bytes
35     Ignore,
36     // Mark erraneous bytes by prepending them with \xFF\x00; real \xFF
37     // is escaped to \xFF\xFF
38     Mark,
39   };
40 
m_fd(fd)41   Terminal(int fd = -1) : m_fd(fd) {}
42 
43   ~Terminal() = default;
44 
45   bool IsATerminal() const;
46 
GetFileDescriptor()47   int GetFileDescriptor() const { return m_fd; }
48 
SetFileDescriptor(int fd)49   void SetFileDescriptor(int fd) { m_fd = fd; }
50 
FileDescriptorIsValid()51   bool FileDescriptorIsValid() const { return m_fd != -1; }
52 
Clear()53   void Clear() { m_fd = -1; }
54 
55   llvm::Error SetEcho(bool enabled);
56 
57   llvm::Error SetCanonical(bool enabled);
58 
59   llvm::Error SetRaw();
60 
61   llvm::Error SetBaudRate(unsigned int baud_rate);
62 
63   llvm::Error SetStopBits(unsigned int stop_bits);
64 
65   llvm::Error SetParity(Parity parity);
66 
67   llvm::Error SetParityCheck(ParityCheck parity_check);
68 
69   llvm::Error SetHardwareFlowControl(bool enabled);
70 
71 protected:
72   struct Data;
73 
74   int m_fd; // This may or may not be a terminal file descriptor
75 
76   llvm::Expected<Data> GetData();
77   llvm::Error SetData(const Data &data);
78 
79   friend class TerminalState;
80 };
81 
82 /// \class TerminalState Terminal.h "lldb/Host/Terminal.h"
83 /// A RAII-friendly terminal state saving/restoring class.
84 ///
85 /// This class can be used to remember the terminal state for a file
86 /// descriptor and later restore that state as it originally was.
87 class TerminalState {
88 public:
89   /// Construct a new instance and optionally save terminal state.
90   ///
91   /// \param[in] term
92   ///     The Terminal instance holding the file descriptor to save the state
93   ///     of.  If the instance is not associated with a fd, no state will
94   ///     be saved.
95   ///
96   /// \param[in] save_process_group
97   ///     If \b true, save the process group settings, else do not
98   ///     save the process group settings for a TTY.
99   TerminalState(Terminal term = -1, bool save_process_group = false);
100 
101   /// Destroy the instance, restoring terminal state if saved.  If restoring
102   /// state is undesirable, the instance needs to be reset before destruction.
103   ~TerminalState();
104 
105   /// Save the TTY state for \a fd.
106   ///
107   /// Save the current state of the TTY for the file descriptor "fd" and if
108   /// "save_process_group" is true, attempt to save the process group info for
109   /// the TTY.
110   ///
111   /// \param[in] term
112   ///     The Terminal instance holding fd to save.
113   ///
114   /// \param[in] save_process_group
115   ///     If \b true, save the process group settings, else do not
116   ///     save the process group settings for a TTY.
117   ///
118   /// \return
119   ///     Returns \b true if \a fd describes a TTY and if the state
120   ///     was able to be saved, \b false otherwise.
121   bool Save(Terminal term, bool save_process_group);
122 
123   /// Restore the TTY state to the cached state.
124   ///
125   /// Restore the state of the TTY using the cached values from a previous
126   /// call to TerminalState::Save(int,bool).
127   ///
128   /// \return
129   ///     Returns \b true if the TTY state was successfully restored,
130   ///     \b false otherwise.
131   bool Restore() const;
132 
133   /// Test for valid cached TTY state information.
134   ///
135   /// \return
136   ///     Returns \b true if this object has valid saved TTY state
137   ///     settings that can be used to restore a previous state,
138   ///     \b false otherwise.
139   bool IsValid() const;
140 
141   void Clear();
142 
143 protected:
144   /// Test if tflags is valid.
145   ///
146   /// \return
147   ///     Returns \b true if \a m_tflags is valid and can be restored,
148   ///     \b false otherwise.
149   bool TFlagsIsValid() const;
150 
151   /// Test if ttystate is valid.
152   ///
153   /// \return
154   ///     Returns \b true if \a m_ttystate is valid and can be
155   ///     restored, \b false otherwise.
156   bool TTYStateIsValid() const;
157 
158   /// Test if the process group information is valid.
159   ///
160   /// \return
161   ///     Returns \b true if \a m_process_group is valid and can be
162   ///     restored, \b false otherwise.
163   bool ProcessGroupIsValid() const;
164 
165   // Member variables
166   Terminal m_tty;                         ///< A terminal
167   int m_tflags = -1;                      ///< Cached tflags information.
168   std::unique_ptr<Terminal::Data> m_data; ///< Platform-specific implementation.
169   lldb::pid_t m_process_group = -1;       ///< Cached process group information.
170 };
171 
172 } // namespace lldb_private
173 
174 #endif // LLDB_HOST_TERMINAL_H
175