1 //===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Host/PseudoTerminal.h"
11 #include "lldb/Host/Config.h"
17 #if defined(TIOCSCTTY)
18 #include <sys/ioctl.h>
21 #include "lldb/Host/PosixApi.h"
23 #if defined(__ANDROID__)
24 int posix_openpt(int flags);
27 using namespace lldb_utility;
29 //----------------------------------------------------------------------
30 // PseudoTerminal constructor
31 //----------------------------------------------------------------------
32 PseudoTerminal::PseudoTerminal()
33 : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {}
35 //----------------------------------------------------------------------
38 // The destructor will close the master and slave file descriptors
39 // if they are valid and ownership has not been released using the
40 // ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor()
42 //----------------------------------------------------------------------
43 PseudoTerminal::~PseudoTerminal() {
44 CloseMasterFileDescriptor();
45 CloseSlaveFileDescriptor();
48 //----------------------------------------------------------------------
49 // Close the master file descriptor if it is valid.
50 //----------------------------------------------------------------------
51 void PseudoTerminal::CloseMasterFileDescriptor() {
52 if (m_master_fd >= 0) {
54 m_master_fd = invalid_fd;
58 //----------------------------------------------------------------------
59 // Close the slave file descriptor if it is valid.
60 //----------------------------------------------------------------------
61 void PseudoTerminal::CloseSlaveFileDescriptor() {
62 if (m_slave_fd >= 0) {
64 m_slave_fd = invalid_fd;
68 //----------------------------------------------------------------------
69 // Open the first available pseudo terminal with OFLAG as the
70 // permissions. The file descriptor is stored in this object and can
71 // be accessed with the MasterFileDescriptor() accessor. The
72 // ownership of the master file descriptor can be released using
73 // the ReleaseMasterFileDescriptor() accessor. If this object has
74 // a valid master files descriptor when its destructor is called, it
75 // will close the master file descriptor, therefore clients must
76 // call ReleaseMasterFileDescriptor() if they wish to use the master
77 // file descriptor after this object is out of scope or destroyed.
80 // True when successful, false indicating an error occurred.
81 //----------------------------------------------------------------------
82 bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
87 #if !defined(LLDB_DISABLE_POSIX)
88 // Open the master side of a pseudo terminal
89 m_master_fd = ::posix_openpt(oflag);
90 if (m_master_fd < 0) {
92 ::strerror_r(errno, error_str, error_len);
96 // Grant access to the slave pseudo terminal
97 if (::grantpt(m_master_fd) < 0) {
99 ::strerror_r(errno, error_str, error_len);
100 CloseMasterFileDescriptor();
104 // Clear the lock flag on the slave pseudo terminal
105 if (::unlockpt(m_master_fd) < 0) {
107 ::strerror_r(errno, error_str, error_len);
108 CloseMasterFileDescriptor();
115 ::snprintf(error_str, error_len, "%s", "pseudo terminal not supported");
120 //----------------------------------------------------------------------
121 // Open the slave pseudo terminal for the current master pseudo
122 // terminal. A master pseudo terminal should already be valid prior to
123 // calling this function (see OpenFirstAvailableMaster()).
124 // The file descriptor is stored this object's member variables and can
125 // be accessed via the GetSlaveFileDescriptor(), or released using the
126 // ReleaseSlaveFileDescriptor() member function.
129 // True when successful, false indicating an error occurred.
130 //----------------------------------------------------------------------
131 bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
135 CloseSlaveFileDescriptor();
137 // Open the master side of a pseudo terminal
138 const char *slave_name = GetSlaveName(error_str, error_len);
140 if (slave_name == nullptr)
143 m_slave_fd = ::open(slave_name, oflag);
145 if (m_slave_fd < 0) {
147 ::strerror_r(errno, error_str, error_len);
154 //----------------------------------------------------------------------
155 // Get the name of the slave pseudo terminal. A master pseudo terminal
156 // should already be valid prior to calling this function (see
157 // OpenFirstAvailableMaster()).
160 // NULL if no valid master pseudo terminal or if ptsname() fails.
161 // The name of the slave pseudo terminal as a NULL terminated C string
162 // that comes from static memory, so a copy of the string should be
163 // made as subsequent calls can change this value.
164 //----------------------------------------------------------------------
165 const char *PseudoTerminal::GetSlaveName(char *error_str,
166 size_t error_len) const {
170 if (m_master_fd < 0) {
172 ::snprintf(error_str, error_len, "%s",
173 "master file descriptor is invalid");
176 const char *slave_name = ::ptsname(m_master_fd);
178 if (error_str && slave_name == nullptr)
179 ::strerror_r(errno, error_str, error_len);
184 //----------------------------------------------------------------------
185 // Fork a child process and have its stdio routed to a pseudo terminal.
187 // In the parent process when a valid pid is returned, the master file
188 // descriptor can be used as a read/write access to stdio of the
191 // In the child process the stdin/stdout/stderr will already be routed
192 // to the slave pseudo terminal and the master file descriptor will be
193 // closed as it is no longer needed by the child process.
195 // This class will close the file descriptors for the master/slave
196 // when the destructor is called, so be sure to call
197 // ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any
198 // file descriptors are going to be used past the lifespan of this
202 // in the parent process: the pid of the child, or -1 if fork fails
203 // in the child process: zero
204 //----------------------------------------------------------------------
205 lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
208 pid_t pid = LLDB_INVALID_PROCESS_ID;
209 #if !defined(LLDB_DISABLE_POSIX)
212 if (OpenFirstAvailableMaster(flags, error_str, error_len)) {
213 // Successfully opened our master pseudo terminal
219 ::strerror_r(errno, error_str, error_len);
220 } else if (pid == 0) {
224 if (OpenSlave(O_RDWR, error_str, error_len)) {
225 // Successfully opened slave
227 // Master FD should have O_CLOEXEC set, but let's close it just in
229 CloseMasterFileDescriptor();
231 #if defined(TIOCSCTTY)
232 // Acquire the controlling terminal
233 if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
235 ::strerror_r(errno, error_str, error_len);
238 // Duplicate all stdio file descriptors to the slave pseudo terminal
239 if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
240 if (error_str && !error_str[0])
241 ::strerror_r(errno, error_str, error_len);
244 if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
245 if (error_str && !error_str[0])
246 ::strerror_r(errno, error_str, error_len);
249 if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
250 if (error_str && !error_str[0])
251 ::strerror_r(errno, error_str, error_len);
256 // Do nothing and let the pid get returned!
263 //----------------------------------------------------------------------
264 // The master file descriptor accessor. This object retains ownership
265 // of the master file descriptor when this accessor is used. Use
266 // ReleaseMasterFileDescriptor() if you wish this object to release
267 // ownership of the master file descriptor.
269 // Returns the master file descriptor, or -1 if the master file
270 // descriptor is not currently valid.
271 //----------------------------------------------------------------------
272 int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; }
274 //----------------------------------------------------------------------
275 // The slave file descriptor accessor.
277 // Returns the slave file descriptor, or -1 if the slave file
278 // descriptor is not currently valid.
279 //----------------------------------------------------------------------
280 int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; }
282 //----------------------------------------------------------------------
283 // Release ownership of the master pseudo terminal file descriptor
284 // without closing it. The destructor for this class will close the
285 // master file descriptor if the ownership isn't released using this
286 // call and the master file descriptor has been opened.
287 //----------------------------------------------------------------------
288 int PseudoTerminal::ReleaseMasterFileDescriptor() {
289 // Release ownership of the master pseudo terminal file
290 // descriptor without closing it. (the destructor for this
291 // class will close it otherwise!)
292 int fd = m_master_fd;
293 m_master_fd = invalid_fd;
297 //----------------------------------------------------------------------
298 // Release ownership of the slave pseudo terminal file descriptor
299 // without closing it. The destructor for this class will close the
300 // slave file descriptor if the ownership isn't released using this
301 // call and the slave file descriptor has been opened.
302 //----------------------------------------------------------------------
303 int PseudoTerminal::ReleaseSlaveFileDescriptor() {
304 // Release ownership of the slave pseudo terminal file
305 // descriptor without closing it (the destructor for this
306 // class will close it otherwise!)
308 m_slave_fd = invalid_fd;