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