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