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