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