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