blob: 98d581def4c3841990be4e28650aff64f749097e [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"
22// empty functions
23int posix_openpt(int flag) { return 0; }
24
25int strerror_r(int errnum, char *buf, size_t buflen) { return 0; }
26
27int unlockpt(int fd) { return 0; }
28int grantpt(int fd) { return 0; }
29char *ptsname(int fd) { return 0; }
30
31pid_t fork(void) { return 0; }
32pid_t setsid(void) { return 0; }
33#endif
34
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035using namespace lldb_utility;
36
37//----------------------------------------------------------------------
38// PseudoTerminal constructor
39//----------------------------------------------------------------------
40PseudoTerminal::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//----------------------------------------------------------------------
54PseudoTerminal::~PseudoTerminal ()
55{
56 CloseMasterFileDescriptor();
57 CloseSlaveFileDescriptor();
58}
59
60//----------------------------------------------------------------------
61// Close the master file descriptor if it is valid.
62//----------------------------------------------------------------------
63void
64PseudoTerminal::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//----------------------------------------------------------------------
76void
77PseudoTerminal::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//----------------------------------------------------------------------
100bool
101PseudoTerminal::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//----------------------------------------------------------------------
147bool
148PseudoTerminal::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//----------------------------------------------------------------------
186const char*
187PseudoTerminal::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//----------------------------------------------------------------------
228lldb::pid_t
229PseudoTerminal::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
Greg Clayton000aeb82011-02-09 17:41:27 +0000257#if defined(TIOCSCTTY)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 // 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//----------------------------------------------------------------------
303int
304PseudoTerminal::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//----------------------------------------------------------------------
315int
316PseudoTerminal::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//----------------------------------------------------------------------
327int
328PseudoTerminal::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//----------------------------------------------------------------------
344int
345PseudoTerminal::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