1 | //===-- PseudoTerminal.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_PSEUDOTERMINAL_H |
10 | #define LLDB_HOST_PSEUDOTERMINAL_H |
11 | |
12 | #include "lldb/lldb-defines.h" |
13 | #include "llvm/Support/Error.h" |
14 | #include <fcntl.h> |
15 | #include <string> |
16 | |
17 | namespace lldb_private { |
18 | |
19 | /// \class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h" |
20 | /// A pseudo terminal helper class. |
21 | /// |
22 | /// The pseudo terminal class abstracts the use of pseudo terminals on the |
23 | /// host system. |
24 | class PseudoTerminal { |
25 | public: |
26 | enum { |
27 | invalid_fd = -1 ///< Invalid file descriptor value |
28 | }; |
29 | |
30 | /// Default constructor |
31 | /// |
32 | /// Constructs this object with invalid primary and secondary file |
33 | /// descriptors. |
34 | PseudoTerminal(); |
35 | |
36 | /// Destructor |
37 | /// |
38 | /// The destructor will close the primary and secondary file descriptors if |
39 | /// they are valid and ownership has not been released using one of: @li |
40 | /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li |
41 | /// PseudoTerminal::ReleaseSaveFileDescriptor() |
42 | ~PseudoTerminal(); |
43 | |
44 | /// Close the primary file descriptor if it is valid. |
45 | void ClosePrimaryFileDescriptor(); |
46 | |
47 | /// Close the secondary file descriptor if it is valid. |
48 | void CloseSecondaryFileDescriptor(); |
49 | |
50 | /// Fork a child process that uses pseudo terminals for its stdio. |
51 | /// |
52 | /// In the parent process, a call to this function results in a pid being |
53 | /// returned. If the pid is valid, the primary file descriptor can be used |
54 | /// for read/write access to stdio of the child process. |
55 | /// |
56 | /// In the child process the stdin/stdout/stderr will already be routed to |
57 | /// the secondary pseudo terminal and the primary file descriptor will be |
58 | /// closed as it is no longer needed by the child process. |
59 | /// |
60 | /// This class will close the file descriptors for the primary/secondary when |
61 | /// the destructor is called. The file handles can be released using either: |
62 | /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li |
63 | /// PseudoTerminal::ReleaseSaveFileDescriptor() |
64 | /// |
65 | /// \return |
66 | /// \b Parent process: a child process ID that is greater |
67 | /// than zero, or an error if the fork fails. |
68 | /// \b Child process: zero. |
69 | llvm::Expected<lldb::pid_t> Fork(); |
70 | |
71 | /// The primary file descriptor accessor. |
72 | /// |
73 | /// This object retains ownership of the primary file descriptor when this |
74 | /// accessor is used. Users can call the member function |
75 | /// PseudoTerminal::ReleasePrimaryFileDescriptor() if this object should |
76 | /// release ownership of the secondary file descriptor. |
77 | /// |
78 | /// \return |
79 | /// The primary file descriptor, or PseudoTerminal::invalid_fd |
80 | /// if the primary file descriptor is not currently valid. |
81 | /// |
82 | /// \see PseudoTerminal::ReleasePrimaryFileDescriptor() |
83 | int GetPrimaryFileDescriptor() const; |
84 | |
85 | /// The secondary file descriptor accessor. |
86 | /// |
87 | /// This object retains ownership of the secondary file descriptor when this |
88 | /// accessor is used. Users can call the member function |
89 | /// PseudoTerminal::ReleaseSecondaryFileDescriptor() if this object should |
90 | /// release ownership of the secondary file descriptor. |
91 | /// |
92 | /// \return |
93 | /// The secondary file descriptor, or PseudoTerminal::invalid_fd |
94 | /// if the secondary file descriptor is not currently valid. |
95 | /// |
96 | /// \see PseudoTerminal::ReleaseSecondaryFileDescriptor() |
97 | int GetSecondaryFileDescriptor() const; |
98 | |
99 | /// Get the name of the secondary pseudo terminal. |
100 | /// |
101 | /// A primary pseudo terminal should already be valid prior to |
102 | /// calling this function. |
103 | /// |
104 | /// \return |
105 | /// The name of the secondary pseudo terminal. |
106 | /// |
107 | /// \see PseudoTerminal::OpenFirstAvailablePrimary() |
108 | std::string GetSecondaryName() const; |
109 | |
110 | /// Open the first available pseudo terminal. |
111 | /// |
112 | /// Opens the first available pseudo terminal with \a oflag as the |
113 | /// permissions. The opened primary file descriptor is stored in this object |
114 | /// and can be accessed by calling the |
115 | /// PseudoTerminal::GetPrimaryFileDescriptor() accessor. Clients can call the |
116 | /// PseudoTerminal::ReleasePrimaryFileDescriptor() accessor function if they |
117 | /// wish to use the primary file descriptor beyond the lifespan of this |
118 | /// object. |
119 | /// |
120 | /// If this object still has a valid primary file descriptor when its |
121 | /// destructor is called, it will close it. |
122 | /// |
123 | /// \param[in] oflag |
124 | /// Flags to use when calling \c posix_openpt(\a oflag). |
125 | /// A value of "O_RDWR|O_NOCTTY" is suggested. |
126 | /// |
127 | /// \see PseudoTerminal::GetPrimaryFileDescriptor() @see |
128 | /// PseudoTerminal::ReleasePrimaryFileDescriptor() |
129 | llvm::Error OpenFirstAvailablePrimary(int oflag); |
130 | |
131 | /// Open the secondary for the current primary pseudo terminal. |
132 | /// |
133 | /// A primary pseudo terminal should already be valid prior to |
134 | /// calling this function. The opened secondary file descriptor is stored in |
135 | /// this object and can be accessed by calling the |
136 | /// PseudoTerminal::GetSecondaryFileDescriptor() accessor. Clients can call |
137 | /// the PseudoTerminal::ReleaseSecondaryFileDescriptor() accessor function if |
138 | /// they wish to use the secondary file descriptor beyond the lifespan of this |
139 | /// object. |
140 | /// |
141 | /// If this object still has a valid secondary file descriptor when its |
142 | /// destructor is called, it will close it. |
143 | /// |
144 | /// \param[in] oflag |
145 | /// Flags to use when calling \c open(\a oflag). |
146 | /// |
147 | /// \see PseudoTerminal::OpenFirstAvailablePrimary() @see |
148 | /// PseudoTerminal::GetSecondaryFileDescriptor() @see |
149 | /// PseudoTerminal::ReleaseSecondaryFileDescriptor() |
150 | llvm::Error OpenSecondary(int oflag); |
151 | |
152 | /// Release the primary file descriptor. |
153 | /// |
154 | /// Releases ownership of the primary pseudo terminal file descriptor without |
155 | /// closing it. The destructor for this class will close the primary file |
156 | /// descriptor if the ownership isn't released using this call and the |
157 | /// primary file descriptor has been opened. |
158 | /// |
159 | /// \return |
160 | /// The primary file descriptor, or PseudoTerminal::invalid_fd |
161 | /// if the mast file descriptor is not currently valid. |
162 | int ReleasePrimaryFileDescriptor(); |
163 | |
164 | /// Release the secondary file descriptor. |
165 | /// |
166 | /// Release ownership of the secondary pseudo terminal file descriptor without |
167 | /// closing it. The destructor for this class will close the secondary file |
168 | /// descriptor if the ownership isn't released using this call and the |
169 | /// secondary file descriptor has been opened. |
170 | /// |
171 | /// \return |
172 | /// The secondary file descriptor, or PseudoTerminal::invalid_fd |
173 | /// if the secondary file descriptor is not currently valid. |
174 | int ReleaseSecondaryFileDescriptor(); |
175 | |
176 | protected: |
177 | // Member variables |
178 | int m_primary_fd = invalid_fd; ///< The file descriptor for the primary. |
179 | int m_secondary_fd = invalid_fd; ///< The file descriptor for the secondary. |
180 | |
181 | private: |
182 | PseudoTerminal(const PseudoTerminal &) = delete; |
183 | const PseudoTerminal &operator=(const PseudoTerminal &) = delete; |
184 | }; |
185 | |
186 | } // namespace lldb_private |
187 | |
188 | #endif // LLDB_HOST_PSEUDOTERMINAL_H |
189 | |