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