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