1 //===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Host/PseudoTerminal.h"
11 #include "lldb/Host/Config.h"
12
13 #include "llvm/Support/Errno.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #if defined(TIOCSCTTY)
19 #include <sys/ioctl.h>
20 #endif
21
22 #include "lldb/Host/PosixApi.h"
23
24 #if defined(__ANDROID__)
25 int posix_openpt(int flags);
26 #endif
27
28 using namespace lldb_private;
29
30 //----------------------------------------------------------------------
31 // Write string describing error number
32 //----------------------------------------------------------------------
ErrnoToStr(char * error_str,size_t error_len)33 static void ErrnoToStr(char *error_str, size_t error_len) {
34 std::string strerror = llvm::sys::StrError();
35 ::snprintf(error_str, error_len, "%s", strerror.c_str());
36 }
37
38 //----------------------------------------------------------------------
39 // PseudoTerminal constructor
40 //----------------------------------------------------------------------
PseudoTerminal()41 PseudoTerminal::PseudoTerminal()
42 : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {}
43
44 //----------------------------------------------------------------------
45 // Destructor
46 //
47 // The destructor will close the master and slave file descriptors if they are
48 // valid and ownership has not been released using the
49 // ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() member
50 // functions.
51 //----------------------------------------------------------------------
~PseudoTerminal()52 PseudoTerminal::~PseudoTerminal() {
53 CloseMasterFileDescriptor();
54 CloseSlaveFileDescriptor();
55 }
56
57 //----------------------------------------------------------------------
58 // Close the master file descriptor if it is valid.
59 //----------------------------------------------------------------------
CloseMasterFileDescriptor()60 void PseudoTerminal::CloseMasterFileDescriptor() {
61 if (m_master_fd >= 0) {
62 ::close(m_master_fd);
63 m_master_fd = invalid_fd;
64 }
65 }
66
67 //----------------------------------------------------------------------
68 // Close the slave file descriptor if it is valid.
69 //----------------------------------------------------------------------
CloseSlaveFileDescriptor()70 void PseudoTerminal::CloseSlaveFileDescriptor() {
71 if (m_slave_fd >= 0) {
72 ::close(m_slave_fd);
73 m_slave_fd = invalid_fd;
74 }
75 }
76
77 //----------------------------------------------------------------------
78 // Open the first available pseudo terminal with OFLAG as the permissions. The
79 // file descriptor is stored in this object and can be accessed with the
80 // MasterFileDescriptor() accessor. The ownership of the master file descriptor
81 // can be released using the ReleaseMasterFileDescriptor() accessor. If this
82 // object has a valid master files descriptor when its destructor is called, it
83 // will close the master file descriptor, therefore clients must call
84 // ReleaseMasterFileDescriptor() if they wish to use the master file descriptor
85 // after this object is out of scope or destroyed.
86 //
87 // RETURNS:
88 // True when successful, false indicating an error occurred.
89 //----------------------------------------------------------------------
OpenFirstAvailableMaster(int oflag,char * error_str,size_t error_len)90 bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
91 size_t error_len) {
92 if (error_str)
93 error_str[0] = '\0';
94
95 #if !defined(LLDB_DISABLE_POSIX)
96 // Open the master side of a pseudo terminal
97 m_master_fd = ::posix_openpt(oflag);
98 if (m_master_fd < 0) {
99 if (error_str)
100 ErrnoToStr(error_str, error_len);
101 return false;
102 }
103
104 // Grant access to the slave pseudo terminal
105 if (::grantpt(m_master_fd) < 0) {
106 if (error_str)
107 ErrnoToStr(error_str, error_len);
108 CloseMasterFileDescriptor();
109 return false;
110 }
111
112 // Clear the lock flag on the slave pseudo terminal
113 if (::unlockpt(m_master_fd) < 0) {
114 if (error_str)
115 ErrnoToStr(error_str, error_len);
116 CloseMasterFileDescriptor();
117 return false;
118 }
119
120 return true;
121 #else
122 if (error_str)
123 ::snprintf(error_str, error_len, "%s", "pseudo terminal not supported");
124 return false;
125 #endif
126 }
127
128 //----------------------------------------------------------------------
129 // Open the slave pseudo terminal for the current master pseudo terminal. A
130 // master pseudo terminal should already be valid prior to calling this
131 // function (see OpenFirstAvailableMaster()). The file descriptor is stored
132 // this object's member variables and can be accessed via the
133 // GetSlaveFileDescriptor(), or released using the ReleaseSlaveFileDescriptor()
134 // member function.
135 //
136 // RETURNS:
137 // True when successful, false indicating an error occurred.
138 //----------------------------------------------------------------------
OpenSlave(int oflag,char * error_str,size_t error_len)139 bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
140 if (error_str)
141 error_str[0] = '\0';
142
143 CloseSlaveFileDescriptor();
144
145 // Open the master side of a pseudo terminal
146 const char *slave_name = GetSlaveName(error_str, error_len);
147
148 if (slave_name == nullptr)
149 return false;
150
151 m_slave_fd = ::open(slave_name, oflag);
152
153 if (m_slave_fd < 0) {
154 if (error_str)
155 ErrnoToStr(error_str, error_len);
156 return false;
157 }
158
159 return true;
160 }
161
162 //----------------------------------------------------------------------
163 // Get the name of the slave pseudo terminal. A master pseudo terminal should
164 // already be valid prior to calling this function (see
165 // OpenFirstAvailableMaster()).
166 //
167 // RETURNS:
168 // NULL if no valid master pseudo terminal or if ptsname() fails.
169 // The name of the slave pseudo terminal as a NULL terminated C string
170 // that comes from static memory, so a copy of the string should be
171 // made as subsequent calls can change this value.
172 //----------------------------------------------------------------------
GetSlaveName(char * error_str,size_t error_len) const173 const char *PseudoTerminal::GetSlaveName(char *error_str,
174 size_t error_len) const {
175 if (error_str)
176 error_str[0] = '\0';
177
178 if (m_master_fd < 0) {
179 if (error_str)
180 ::snprintf(error_str, error_len, "%s",
181 "master file descriptor is invalid");
182 return nullptr;
183 }
184 const char *slave_name = ::ptsname(m_master_fd);
185
186 if (error_str && slave_name == nullptr)
187 ErrnoToStr(error_str, error_len);
188
189 return slave_name;
190 }
191
192 //----------------------------------------------------------------------
193 // Fork a child process and have its stdio routed to a pseudo terminal.
194 //
195 // In the parent process when a valid pid is returned, the master file
196 // descriptor can be used as a read/write access to stdio of the child process.
197 //
198 // In the child process the stdin/stdout/stderr will already be routed to the
199 // slave pseudo terminal and the master file descriptor will be closed as it is
200 // no longer needed by the child process.
201 //
202 // This class will close the file descriptors for the master/slave when the
203 // destructor is called, so be sure to call ReleaseMasterFileDescriptor() or
204 // ReleaseSlaveFileDescriptor() if any file descriptors are going to be used
205 // past the lifespan of this object.
206 //
207 // RETURNS:
208 // in the parent process: the pid of the child, or -1 if fork fails
209 // in the child process: zero
210 //----------------------------------------------------------------------
Fork(char * error_str,size_t error_len)211 lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
212 if (error_str)
213 error_str[0] = '\0';
214 pid_t pid = LLDB_INVALID_PROCESS_ID;
215 #if !defined(LLDB_DISABLE_POSIX)
216 int flags = O_RDWR;
217 flags |= O_CLOEXEC;
218 if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
219 // Successfully opened our master pseudo terminal
220
221 pid = ::fork();
222 if (pid < 0) {
223 // Fork failed
224 if (error_str)
225 ErrnoToStr(error_str, error_len);
226 } else if (pid == 0) {
227 // Child Process
228 ::setsid();
229
230 if (OpenSlave(O_RDWR, error_str, error_len)) {
231 // Successfully opened slave
232
233 // Master FD should have O_CLOEXEC set, but let's close it just in
234 // case...
235 CloseMasterFileDescriptor();
236
237 #if defined(TIOCSCTTY)
238 // Acquire the controlling terminal
239 if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
240 if (error_str)
241 ErrnoToStr(error_str, error_len);
242 }
243 #endif
244 // Duplicate all stdio file descriptors to the slave pseudo terminal
245 if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
246 if (error_str && !error_str[0])
247 ErrnoToStr(error_str, error_len);
248 }
249
250 if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
251 if (error_str && !error_str[0])
252 ErrnoToStr(error_str, error_len);
253 }
254
255 if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
256 if (error_str && !error_str[0])
257 ErrnoToStr(error_str, error_len);
258 }
259 }
260 } else {
261 // Parent Process
262 // Do nothing and let the pid get returned!
263 }
264 }
265 #endif
266 return pid;
267 }
268
269 //----------------------------------------------------------------------
270 // The master file descriptor accessor. This object retains ownership of the
271 // master file descriptor when this accessor is used. Use
272 // ReleaseMasterFileDescriptor() if you wish this object to release ownership
273 // of the master file descriptor.
274 //
275 // Returns the master file descriptor, or -1 if the master file descriptor is
276 // not currently valid.
277 //----------------------------------------------------------------------
GetMasterFileDescriptor() const278 int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
279
280 //----------------------------------------------------------------------
281 // The slave file descriptor accessor.
282 //
283 // Returns the slave file descriptor, or -1 if the slave file descriptor is not
284 // currently valid.
285 //----------------------------------------------------------------------
GetSlaveFileDescriptor() const286 int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; }
287
288 //----------------------------------------------------------------------
289 // Release ownership of the master pseudo terminal file descriptor without
290 // closing it. The destructor for this class will close the master file
291 // descriptor if the ownership isn't released using this call and the master
292 // file descriptor has been opened.
293 //----------------------------------------------------------------------
ReleaseMasterFileDescriptor()294 int PseudoTerminal::ReleaseMasterFileDescriptor() {
295 // Release ownership of the master pseudo terminal file descriptor without
296 // closing it. (the destructor for this class will close it otherwise!)
297 int fd = m_master_fd;
298 m_master_fd = invalid_fd;
299 return fd;
300 }
301
302 //----------------------------------------------------------------------
303 // Release ownership of the slave pseudo terminal file descriptor without
304 // closing it. The destructor for this class will close the slave file
305 // descriptor if the ownership isn't released using this call and the slave
306 // file descriptor has been opened.
307 //----------------------------------------------------------------------
ReleaseSlaveFileDescriptor()308 int PseudoTerminal::ReleaseSlaveFileDescriptor() {
309 // Release ownership of the slave pseudo terminal file descriptor without
310 // closing it (the destructor for this class will close it otherwise!)
311 int fd = m_slave_fd;
312 m_slave_fd = invalid_fd;
313 return fd;
314 }
315