diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Utility/PseudoTerminal.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Utility/PseudoTerminal.cpp | 311 |
1 files changed, 0 insertions, 311 deletions
diff --git a/contrib/llvm/tools/lldb/source/Utility/PseudoTerminal.cpp b/contrib/llvm/tools/lldb/source/Utility/PseudoTerminal.cpp deleted file mode 100644 index 4d99a56..0000000 --- a/contrib/llvm/tools/lldb/source/Utility/PseudoTerminal.cpp +++ /dev/null @@ -1,311 +0,0 @@ -//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Utility/PseudoTerminal.h" -#include "lldb/Host/Config.h" - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#if defined(TIOCSCTTY) -#include <sys/ioctl.h> -#endif - -#include "lldb/Host/PosixApi.h" - -#if defined(__ANDROID__) -int posix_openpt(int flags); -#endif - -using namespace lldb_utility; - -//---------------------------------------------------------------------- -// PseudoTerminal constructor -//---------------------------------------------------------------------- -PseudoTerminal::PseudoTerminal() - : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {} - -//---------------------------------------------------------------------- -// Destructor -// -// The destructor will close the master and slave file descriptors -// if they are valid and ownership has not been released using the -// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() -// member functions. -//---------------------------------------------------------------------- -PseudoTerminal::~PseudoTerminal() { - CloseMasterFileDescriptor(); - CloseSlaveFileDescriptor(); -} - -//---------------------------------------------------------------------- -// Close the master file descriptor if it is valid. -//---------------------------------------------------------------------- -void PseudoTerminal::CloseMasterFileDescriptor() { - if (m_master_fd >= 0) { - ::close(m_master_fd); - m_master_fd = invalid_fd; - } -} - -//---------------------------------------------------------------------- -// Close the slave file descriptor if it is valid. -//---------------------------------------------------------------------- -void PseudoTerminal::CloseSlaveFileDescriptor() { - if (m_slave_fd >= 0) { - ::close(m_slave_fd); - m_slave_fd = invalid_fd; - } -} - -//---------------------------------------------------------------------- -// Open the first available pseudo terminal with OFLAG as the -// permissions. The file descriptor is stored in this object and can -// be accessed with the MasterFileDescriptor() accessor. The -// ownership of the master file descriptor can be released using -// the ReleaseMasterFileDescriptor() accessor. If this object has -// a valid master files descriptor when its destructor is called, it -// will close the master file descriptor, therefore clients must -// call ReleaseMasterFileDescriptor() if they wish to use the master -// file descriptor after this object is out of scope or destroyed. -// -// RETURNS: -// True when successful, false indicating an error occurred. -//---------------------------------------------------------------------- -bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str, - size_t error_len) { - if (error_str) - error_str[0] = '\0'; - -#if !defined(LLDB_DISABLE_POSIX) - // Open the master side of a pseudo terminal - m_master_fd = ::posix_openpt(oflag); - if (m_master_fd < 0) { - if (error_str) - ::strerror_r(errno, error_str, error_len); - return false; - } - - // Grant access to the slave pseudo terminal - if (::grantpt(m_master_fd) < 0) { - if (error_str) - ::strerror_r(errno, error_str, error_len); - CloseMasterFileDescriptor(); - return false; - } - - // Clear the lock flag on the slave pseudo terminal - if (::unlockpt(m_master_fd) < 0) { - if (error_str) - ::strerror_r(errno, error_str, error_len); - CloseMasterFileDescriptor(); - return false; - } - - return true; -#else - if (error_str) - ::snprintf(error_str, error_len, "%s", - "pseudo terminal not supported"); - return false; -#endif -} - -//---------------------------------------------------------------------- -// Open the slave pseudo terminal for the current master pseudo -// terminal. A master pseudo terminal should already be valid prior to -// calling this function (see OpenFirstAvailableMaster()). -// The file descriptor is stored this object's member variables and can -// be accessed via the GetSlaveFileDescriptor(), or released using the -// ReleaseSlaveFileDescriptor() member function. -// -// RETURNS: -// True when successful, false indicating an error occurred. -//---------------------------------------------------------------------- -bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) { - if (error_str) - error_str[0] = '\0'; - - CloseSlaveFileDescriptor(); - - // Open the master side of a pseudo terminal - const char *slave_name = GetSlaveName(error_str, error_len); - - if (slave_name == nullptr) - return false; - - m_slave_fd = ::open(slave_name, oflag); - - if (m_slave_fd < 0) { - if (error_str) - ::strerror_r(errno, error_str, error_len); - return false; - } - - return true; -} - -//---------------------------------------------------------------------- -// Get the name of the slave pseudo terminal. A master pseudo terminal -// should already be valid prior to calling this function (see -// OpenFirstAvailableMaster()). -// -// RETURNS: -// NULL if no valid master pseudo terminal or if ptsname() fails. -// The name of the slave pseudo terminal as a NULL terminated C string -// that comes from static memory, so a copy of the string should be -// made as subsequent calls can change this value. -//---------------------------------------------------------------------- -const char *PseudoTerminal::GetSlaveName(char *error_str, - size_t error_len) const { - if (error_str) - error_str[0] = '\0'; - - if (m_master_fd < 0) { - if (error_str) - ::snprintf(error_str, error_len, "%s", - "master file descriptor is invalid"); - return nullptr; - } - const char *slave_name = ::ptsname(m_master_fd); - - if (error_str && slave_name == nullptr) - ::strerror_r(errno, error_str, error_len); - - return slave_name; -} - -//---------------------------------------------------------------------- -// Fork a child process and have its stdio routed to a pseudo terminal. -// -// In the parent process when a valid pid is returned, the master file -// descriptor can be used as a read/write access to stdio of the -// child process. -// -// In the child process the stdin/stdout/stderr will already be routed -// to the slave pseudo terminal and the master file descriptor will be -// closed as it is no longer needed by the child process. -// -// This class will close the file descriptors for the master/slave -// when the destructor is called, so be sure to call -// ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any -// file descriptors are going to be used past the lifespan of this -// object. -// -// RETURNS: -// in the parent process: the pid of the child, or -1 if fork fails -// in the child process: zero -//---------------------------------------------------------------------- -lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) { - if (error_str) - error_str[0] = '\0'; - pid_t pid = LLDB_INVALID_PROCESS_ID; -#if !defined(LLDB_DISABLE_POSIX) - int flags = O_RDWR; - flags |= O_CLOEXEC; - if (OpenFirstAvailableMaster(flags, error_str, error_len)) { - // Successfully opened our master pseudo terminal - - pid = ::fork(); - if (pid < 0) { - // Fork failed - if (error_str) - ::strerror_r(errno, error_str, error_len); - } else if (pid == 0) { - // Child Process - ::setsid(); - - if (OpenSlave(O_RDWR, error_str, error_len)) { - // Successfully opened slave - - // Master FD should have O_CLOEXEC set, but let's close it just in - // case... - CloseMasterFileDescriptor(); - -#if defined(TIOCSCTTY) - // Acquire the controlling terminal - if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) { - if (error_str) - ::strerror_r(errno, error_str, error_len); - } -#endif - // Duplicate all stdio file descriptors to the slave pseudo terminal - if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) { - if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); - } - - if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) { - if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); - } - - if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) { - if (error_str && !error_str[0]) - ::strerror_r(errno, error_str, error_len); - } - } - } else { - // Parent Process - // Do nothing and let the pid get returned! - } - } -#endif - return pid; -} - -//---------------------------------------------------------------------- -// The master file descriptor accessor. This object retains ownership -// of the master file descriptor when this accessor is used. Use -// ReleaseMasterFileDescriptor() if you wish this object to release -// ownership of the master file descriptor. -// -// Returns the master file descriptor, or -1 if the master file -// descriptor is not currently valid. -//---------------------------------------------------------------------- -int PseudoTerminal::GetMasterFileDescriptor() const { return m_master_fd; } - -//---------------------------------------------------------------------- -// The slave file descriptor accessor. -// -// Returns the slave file descriptor, or -1 if the slave file -// descriptor is not currently valid. -//---------------------------------------------------------------------- -int PseudoTerminal::GetSlaveFileDescriptor() const { return m_slave_fd; } - -//---------------------------------------------------------------------- -// Release ownership of the master pseudo terminal file descriptor -// without closing it. The destructor for this class will close the -// master file descriptor if the ownership isn't released using this -// call and the master file descriptor has been opened. -//---------------------------------------------------------------------- -int PseudoTerminal::ReleaseMasterFileDescriptor() { - // Release ownership of the master pseudo terminal file - // descriptor without closing it. (the destructor for this - // class will close it otherwise!) - int fd = m_master_fd; - m_master_fd = invalid_fd; - return fd; -} - -//---------------------------------------------------------------------- -// Release ownership of the slave pseudo terminal file descriptor -// without closing it. The destructor for this class will close the -// slave file descriptor if the ownership isn't released using this -// call and the slave file descriptor has been opened. -//---------------------------------------------------------------------- -int PseudoTerminal::ReleaseSlaveFileDescriptor() { - // Release ownership of the slave pseudo terminal file - // descriptor without closing it (the destructor for this - // class will close it otherwise!) - int fd = m_slave_fd; - m_slave_fd = invalid_fd; - return fd; -} |