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 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 35using 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 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//---------------------------------------------------------------------- 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 355