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