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