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