zturner updated this revision to Diff 88626.

https://reviews.llvm.org/D29964

Files:
  lldb/include/lldb/Host/PseudoTerminal.h
  lldb/include/lldb/Utility/PseudoTerminal.h
  lldb/include/lldb/Utility/VASPrintf.h
  lldb/source/Host/CMakeLists.txt
  lldb/source/Host/common/PseudoTerminal.cpp
  lldb/source/Utility/CMakeLists.txt
  lldb/source/Utility/Error.cpp
  lldb/source/Utility/PseudoTerminal.cpp
  lldb/source/Utility/Stream.cpp
  lldb/source/Utility/VASprintf.cpp
  lldb/unittests/Utility/CMakeLists.txt
  lldb/unittests/Utility/VASprintfTest.cpp

Index: lldb/unittests/Utility/VASprintfTest.cpp
===================================================================
--- /dev/null
+++ lldb/unittests/Utility/VASprintfTest.cpp
@@ -0,0 +1,58 @@
+//===-- VASprintfTest.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/VASprintf.h"
+#include "llvm/ADT/SmallString.h"
+
+#include "gtest/gtest.h"
+
+#include <locale.h>
+
+using namespace lldb_private;
+using namespace llvm;
+
+static void Sprintf(llvm::SmallVectorImpl<char> &Buffer, const char *Fmt, ...) {
+  va_list args;
+  va_start(args, Fmt);
+  VASprintf(Buffer, Fmt, args);
+  va_end(args);
+}
+
+TEST(VASprintfTest, NoBufferResize) {
+  std::string TestStr("small");
+
+  llvm::SmallString<32> BigBuffer;
+  Sprintf(BigBuffer, "%s", TestStr.c_str());
+  EXPECT_STREQ(TestStr.c_str(), BigBuffer.c_str());
+  EXPECT_EQ(TestStr.size(), BigBuffer.size());
+}
+
+TEST(VASprintfTest, BufferResize) {
+  std::string TestStr("bigger");
+  llvm::SmallString<4> SmallBuffer;
+  Sprintf(SmallBuffer, "%s", TestStr.c_str());
+  EXPECT_STREQ(TestStr.c_str(), SmallBuffer.c_str());
+  EXPECT_EQ(TestStr.size(), SmallBuffer.size());
+}
+
+TEST(VASprintfTest, EncodingError) {
+  // Save the current locale first.
+  std::string Current(::setlocale(LC_ALL, nullptr));
+
+  setlocale(LC_ALL, ".932");
+
+  wchar_t Invalid[2];
+  Invalid[0] = 129;
+  Invalid[1] = 0;
+  llvm::SmallString<32> Buffer;
+  Sprintf(Buffer, "%ls", Invalid);
+  EXPECT_EQ("<Encoding error>", Buffer);
+
+  setlocale(LC_CTYPE, Current.c_str());
+}
Index: lldb/unittests/Utility/CMakeLists.txt
===================================================================
--- lldb/unittests/Utility/CMakeLists.txt
+++ lldb/unittests/Utility/CMakeLists.txt
@@ -4,9 +4,9 @@
   TaskPoolTest.cpp
   TimeoutTest.cpp
   UriParserTest.cpp
+  VASprintfTest.cpp
 
   LINK_LIBS
-      lldbHost
       lldbUtility
     LINK_COMPONENTS
       Support
Index: lldb/source/Utility/VASprintf.cpp
===================================================================
--- /dev/null
+++ lldb/source/Utility/VASprintf.cpp
@@ -0,0 +1,52 @@
+//===-- VASPrintf.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/VASprintf.h"
+
+#include "llvm/ADT/SmallString.h"
+
+using namespace lldb_private;
+
+bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
+                             va_list args) {
+  llvm::SmallString<16> error("<Encoding error>");
+  bool result = true;
+
+  // Copy in case our first call to vsnprintf doesn't fit into our buffer
+  va_list copy_args;
+  va_copy(copy_args, args);
+
+  buf.resize(buf.capacity());
+  // Write up to `capacity` bytes, ignoring the current size.
+  int length = ::vsnprintf(buf.data(), buf.size(), fmt, args);
+  if (length < 0) {
+    buf = error;
+    result = false;
+    goto finish;
+  }
+
+  if (length >= buf.size()) {
+    // The error formatted string didn't fit into our buffer, resize it
+    // to the exact needed size, and retry
+    buf.resize(length + 1);
+    length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
+    if (length < 0) {
+      buf = error;
+      result = false;
+      goto finish;
+    }
+    assert(length < buf.size());
+  }
+  buf.resize(length);
+
+finish:
+  va_end(args);
+  va_end(copy_args);
+  return result;
+}
Index: lldb/source/Utility/Stream.cpp
===================================================================
--- lldb/source/Utility/Stream.cpp
+++ lldb/source/Utility/Stream.cpp
@@ -8,8 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Utility/Stream.h"
-#include "lldb/Host/PosixApi.h"
+
 #include "lldb/Utility/Endian.h"
+#include "lldb/Utility/VASPrintf.h"
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -162,36 +163,14 @@
 // Print some formatted output to the stream.
 //------------------------------------------------------------------
 size_t Stream::PrintfVarArg(const char *format, va_list args) {
-  char str[1024];
-  va_list args_copy;
-
-  va_copy(args_copy, args);
+  llvm::SmallString<1024> buf;
+  VASprintf(buf, format, args);
 
-  size_t bytes_written = 0;
-  // Try and format our string into a fixed buffer first and see if it fits
-  size_t length = ::vsnprintf(str, sizeof(str), format, args);
-  if (length < sizeof(str)) {
-    // Include the NULL termination byte for binary output
-    if (m_flags.Test(eBinary))
-      length += 1;
-    // The formatted string fit into our stack based buffer, so we can just
-    // append that to our packet
-    bytes_written = Write(str, length);
-  } else {
-    // Our stack buffer wasn't big enough to contain the entire formatted
-    // string, so lets let vasprintf create the string for us!
-    char *str_ptr = NULL;
-    length = ::vasprintf(&str_ptr, format, args_copy);
-    if (str_ptr) {
-      // Include the NULL termination byte for binary output
-      if (m_flags.Test(eBinary))
-        length += 1;
-      bytes_written = Write(str_ptr, length);
-      ::free(str_ptr);
-    }
-  }
-  va_end(args_copy);
-  return bytes_written;
+  // Include the NULL termination byte for binary output
+  size_t length = buf.size();
+  if (m_flags.Test(eBinary))
+    ++length;
+  return Write(buf.c_str(), length);
 }
 
 //------------------------------------------------------------------
@@ -358,34 +337,18 @@
 
 size_t Stream::PrintfAsRawHex8(const char *format, ...) {
   va_list args;
-  va_list args_copy;
   va_start(args, format);
-  va_copy(args_copy, args); // Copy this so we
 
-  char str[1024];
-  size_t bytes_written = 0;
-  // Try and format our string into a fixed buffer first and see if it fits
-  size_t length = ::vsnprintf(str, sizeof(str), format, args);
-  if (length < sizeof(str)) {
-    // The formatted string fit into our stack based buffer, so we can just
-    // append that to our packet
-    for (size_t i = 0; i < length; ++i)
-      bytes_written += _PutHex8(str[i], false);
-  } else {
-    // Our stack buffer wasn't big enough to contain the entire formatted
-    // string, so lets let vasprintf create the string for us!
-    char *str_ptr = NULL;
-    length = ::vasprintf(&str_ptr, format, args_copy);
-    if (str_ptr) {
-      for (size_t i = 0; i < length; ++i)
-        bytes_written += _PutHex8(str_ptr[i], false);
-      ::free(str_ptr);
-    }
-  }
+  llvm::SmallString<1024> buf;
+  VASprintf(buf, format, args);
+
+  size_t length = 0;
+  for (char C : buf)
+    length += _PutHex8(C, false);
+
   va_end(args);
-  va_end(args_copy);
 
-  return bytes_written;
+  return length;
 }
 
 size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
Index: lldb/source/Utility/PseudoTerminal.cpp
===================================================================
--- 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;
-}
Index: lldb/source/Utility/Error.cpp
===================================================================
--- lldb/source/Utility/Error.cpp
+++ lldb/source/Utility/Error.cpp
@@ -20,8 +20,8 @@
 #include "llvm/ADT/SmallVector.h"
 
 // Project includes
-#include "lldb/Host/PosixApi.h"
 #include "lldb/Utility/Error.h"
+#include "lldb/Utility/VASPrintf.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -233,25 +233,9 @@
     if (Success())
       SetErrorToGenericError();
 
-    // Try and fit our error into a 1024 byte buffer first...
-    llvm::SmallVector<char, 1024> buf;
-    buf.resize(1024);
-    // Copy in case our first call to vsnprintf doesn't fit into our
-    // allocated buffer above
-    va_list copy_args;
-    va_copy(copy_args, args);
-    unsigned length = ::vsnprintf(buf.data(), buf.size(), format, args);
-    if (length >= buf.size()) {
-      // The error formatted string didn't fit into our buffer, resize it
-      // to the exact needed size, and retry
-      buf.resize(length + 1);
-      length = ::vsnprintf(buf.data(), buf.size(), format, copy_args);
-      va_end(copy_args);
-      assert(length < buf.size());
-    }
-    m_string.assign(buf.data(), length);
-    va_end(args);
-    return length;
+    llvm::SmallString<1024> buf;
+    VASprintf(buf, format, args);
+    return buf.size();
   } else {
     m_string.clear();
   }
Index: lldb/source/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Utility/CMakeLists.txt
+++ lldb/source/Utility/CMakeLists.txt
@@ -4,7 +4,6 @@
   JSON.cpp
   LLDBAssert.cpp
   NameMatches.cpp
-  PseudoTerminal.cpp
   Range.cpp
   RegularExpression.cpp
   SelectHelper.cpp
@@ -16,9 +15,10 @@
   StringLexer.cpp
   TaskPool.cpp
   UriParser.cpp
+  VASprintf.cpp
 
   LINK_LIBS
-    lldbHost
+  # lldbUtility cannot have any dependencies
 
   LINK_COMPONENTS
     Support
Index: lldb/source/Host/common/PseudoTerminal.cpp
===================================================================
--- /dev/null
+++ lldb/source/Host/common/PseudoTerminal.cpp
@@ -0,0 +1,310 @@
+//===-- 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/Host/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;
+}
Index: lldb/source/Host/CMakeLists.txt
===================================================================
--- lldb/source/Host/CMakeLists.txt
+++ lldb/source/Host/CMakeLists.txt
@@ -27,6 +27,7 @@
   common/OptionParser.cpp
   common/PipeBase.cpp
   common/ProcessRunLock.cpp
+  common/PseudoTerminal.cpp
   common/Socket.cpp
   common/SocketAddress.cpp
   common/SoftwareBreakpoint.cpp
Index: lldb/include/lldb/Utility/VASPrintf.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Utility/VASPrintf.h
@@ -0,0 +1,21 @@
+//===-- VASPrintf.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_VASPRINTF_H
+#define LLDB_UTILITY_VASPRINTF_H
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <cstdarg>
+
+namespace lldb_private {
+bool VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt, va_list args);
+}
+
+#endif // #ifdef LLDB_UTILITY_VASPRINTF_H
Index: lldb/include/lldb/Utility/PseudoTerminal.h
===================================================================
--- lldb/include/lldb/Utility/PseudoTerminal.h
+++ /dev/null
@@ -1,252 +0,0 @@
-//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_PseudoTerminal_h_
-#define liblldb_PseudoTerminal_h_
-#if defined(__cplusplus)
-
-#include <fcntl.h>
-#include <string>
-
-#include "lldb/lldb-defines.h"
-
-namespace lldb_utility {
-
-//----------------------------------------------------------------------
-/// @class PseudoTerminal PseudoTerminal.h "lldb/Utility/PseudoTerminal.h"
-/// @brief A pseudo terminal helper class.
-///
-/// The pseudo terminal class abstracts the use of pseudo terminals on
-/// the host system.
-//----------------------------------------------------------------------
-class PseudoTerminal {
-public:
-  enum {
-    invalid_fd = -1 ///< Invalid file descriptor value
-  };
-
-  //------------------------------------------------------------------
-  /// Default constructor
-  ///
-  /// Constructs this object with invalid master and slave file
-  /// descriptors.
-  //------------------------------------------------------------------
-  PseudoTerminal();
-
-  //------------------------------------------------------------------
-  /// Destructor
-  ///
-  /// The destructor will close the master and slave file descriptors
-  /// if they are valid and ownership has not been released using
-  /// one of:
-  /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
-  /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
-  //------------------------------------------------------------------
-  ~PseudoTerminal();
-
-  //------------------------------------------------------------------
-  /// Close the master file descriptor if it is valid.
-  //------------------------------------------------------------------
-  void CloseMasterFileDescriptor();
-
-  //------------------------------------------------------------------
-  /// Close the slave file descriptor if it is valid.
-  //------------------------------------------------------------------
-  void CloseSlaveFileDescriptor();
-
-  //------------------------------------------------------------------
-  /// Fork a child process that uses pseudo terminals for its stdio.
-  ///
-  /// In the parent process, a call to this function results in a pid
-  /// being returned. If the pid is valid, the master file descriptor
-  /// can be used for 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. The file handles can be released
-  /// using either:
-  /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
-  /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
-  ///
-  /// @param[out] error
-  ///     An pointer to an error that can describe any errors that
-  ///     occur. This can be NULL if no error status is desired.
-  ///
-  /// @return
-  ///     @li \b Parent process: a child process ID that is greater
-  ///         than zero, or -1 if the fork fails.
-  ///     @li \b Child process: zero.
-  //------------------------------------------------------------------
-  lldb::pid_t Fork(char *error_str, size_t error_len);
-
-  //------------------------------------------------------------------
-  /// The master file descriptor accessor.
-  ///
-  /// This object retains ownership of the master file descriptor when
-  /// this accessor is used. Users can call the member function
-  /// PseudoTerminal::ReleaseMasterFileDescriptor() if this
-  /// object should release ownership of the slave file descriptor.
-  ///
-  /// @return
-  ///     The master file descriptor, or PseudoTerminal::invalid_fd
-  ///     if the master file  descriptor is not currently valid.
-  ///
-  /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
-  //------------------------------------------------------------------
-  int GetMasterFileDescriptor() const;
-
-  //------------------------------------------------------------------
-  /// The slave file descriptor accessor.
-  ///
-  /// This object retains ownership of the slave file descriptor when
-  /// this accessor is used. Users can call the member function
-  /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this
-  /// object should release ownership of the slave file descriptor.
-  ///
-  /// @return
-  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
-  ///     if the slave file descriptor is not currently valid.
-  ///
-  /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
-  //------------------------------------------------------------------
-  int GetSlaveFileDescriptor() const;
-
-  //------------------------------------------------------------------
-  /// Get the name of the slave pseudo terminal.
-  ///
-  /// A master pseudo terminal should already be valid prior to
-  /// calling this function.
-  ///
-  /// @param[out] error
-  ///     An pointer to an error that can describe any errors that
-  ///     occur. This can be NULL if no error status is desired.
-  ///
-  /// @return
-  ///     The name of the slave pseudo terminal as a NULL terminated
-  ///     C. This string that comes from static memory, so a copy of
-  ///     the string should be made as subsequent calls can change
-  ///     this value. NULL is returned if this object doesn't have
-  ///     a valid master pseudo terminal opened or if the call to
-  ///     \c ptsname() fails.
-  ///
-  /// @see PseudoTerminal::OpenFirstAvailableMaster()
-  //------------------------------------------------------------------
-  const char *GetSlaveName(char *error_str, size_t error_len) const;
-
-  //------------------------------------------------------------------
-  /// Open the first available pseudo terminal.
-  ///
-  /// Opens the first available pseudo terminal with \a oflag as the
-  /// permissions. The opened master file descriptor is stored in this
-  /// object and can be accessed by calling the
-  /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients
-  /// can call the PseudoTerminal::ReleaseMasterFileDescriptor()
-  /// accessor function if they wish to use the master file descriptor
-  /// beyond the lifespan of this object.
-  ///
-  /// If this object still has a valid master file descriptor when its
-  /// destructor is called, it will close it.
-  ///
-  /// @param[in] oflag
-  ///     Flags to use when calling \c posix_openpt(\a oflag).
-  ///     A value of "O_RDWR|O_NOCTTY" is suggested.
-  ///
-  /// @param[out] error
-  ///     An pointer to an error that can describe any errors that
-  ///     occur. This can be NULL if no error status is desired.
-  ///
-  /// @return
-  ///     @li \b true when the master files descriptor is
-  ///         successfully opened.
-  ///     @li \b false if anything goes wrong.
-  ///
-  /// @see PseudoTerminal::GetMasterFileDescriptor()
-  /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
-  //------------------------------------------------------------------
-  bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);
-
-  //------------------------------------------------------------------
-  /// Open the slave for the current master pseudo terminal.
-  ///
-  /// A master pseudo terminal should already be valid prior to
-  /// calling this function. The opened slave file descriptor is
-  /// stored in this object and can be accessed by calling the
-  /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients
-  /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor()
-  /// accessor function if they wish to use the slave file descriptor
-  /// beyond the lifespan of this object.
-  ///
-  /// If this object still has a valid slave file descriptor when its
-  /// destructor is called, it will close it.
-  ///
-  /// @param[in] oflag
-  ///     Flags to use when calling \c open(\a oflag).
-  ///
-  /// @param[out] error
-  ///     An pointer to an error that can describe any errors that
-  ///     occur. This can be NULL if no error status is desired.
-  ///
-  /// @return
-  ///     @li \b true when the master files descriptor is
-  ///         successfully opened.
-  ///     @li \b false if anything goes wrong.
-  ///
-  /// @see PseudoTerminal::OpenFirstAvailableMaster()
-  /// @see PseudoTerminal::GetSlaveFileDescriptor()
-  /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
-  //------------------------------------------------------------------
-  bool OpenSlave(int oflag, char *error_str, size_t error_len);
-
-  //------------------------------------------------------------------
-  /// Release the master file descriptor.
-  ///
-  /// Releases 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.
-  ///
-  /// @return
-  ///     The master file descriptor, or PseudoTerminal::invalid_fd
-  ///     if the mast file descriptor is not currently valid.
-  //------------------------------------------------------------------
-  int ReleaseMasterFileDescriptor();
-
-  //------------------------------------------------------------------
-  /// Release the slave file descriptor.
-  ///
-  /// 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.
-  ///
-  /// @return
-  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
-  ///     if the slave file descriptor is not currently valid.
-  //------------------------------------------------------------------
-  int ReleaseSlaveFileDescriptor();
-
-protected:
-  //------------------------------------------------------------------
-  // Member variables
-  //------------------------------------------------------------------
-  int m_master_fd; ///< The file descriptor for the master.
-  int m_slave_fd;  ///< The file descriptor for the slave.
-
-private:
-  DISALLOW_COPY_AND_ASSIGN(PseudoTerminal);
-};
-
-} // namespace lldb_utility
-
-#endif // #if defined(__cplusplus)
-#endif // #ifndef liblldb_PseudoTerminal_h_
Index: lldb/include/lldb/Host/PseudoTerminal.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Host/PseudoTerminal.h
@@ -0,0 +1,252 @@
+//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_HOST_PSEUDOTERMINAL_H
+#define LLDB_HOST_PSEUDOTERMINAL_H
+#if defined(__cplusplus)
+
+#include <fcntl.h>
+#include <string>
+
+#include "lldb/lldb-defines.h"
+
+namespace lldb_utility {
+
+//----------------------------------------------------------------------
+/// @class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h"
+/// @brief A pseudo terminal helper class.
+///
+/// The pseudo terminal class abstracts the use of pseudo terminals on
+/// the host system.
+//----------------------------------------------------------------------
+class PseudoTerminal {
+public:
+  enum {
+    invalid_fd = -1 ///< Invalid file descriptor value
+  };
+
+  //------------------------------------------------------------------
+  /// Default constructor
+  ///
+  /// Constructs this object with invalid master and slave file
+  /// descriptors.
+  //------------------------------------------------------------------
+  PseudoTerminal();
+
+  //------------------------------------------------------------------
+  /// Destructor
+  ///
+  /// The destructor will close the master and slave file descriptors
+  /// if they are valid and ownership has not been released using
+  /// one of:
+  /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+  /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+  //------------------------------------------------------------------
+  ~PseudoTerminal();
+
+  //------------------------------------------------------------------
+  /// Close the master file descriptor if it is valid.
+  //------------------------------------------------------------------
+  void CloseMasterFileDescriptor();
+
+  //------------------------------------------------------------------
+  /// Close the slave file descriptor if it is valid.
+  //------------------------------------------------------------------
+  void CloseSlaveFileDescriptor();
+
+  //------------------------------------------------------------------
+  /// Fork a child process that uses pseudo terminals for its stdio.
+  ///
+  /// In the parent process, a call to this function results in a pid
+  /// being returned. If the pid is valid, the master file descriptor
+  /// can be used for 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. The file handles can be released
+  /// using either:
+  /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+  /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+  ///
+  /// @param[out] error
+  ///     An pointer to an error that can describe any errors that
+  ///     occur. This can be NULL if no error status is desired.
+  ///
+  /// @return
+  ///     @li \b Parent process: a child process ID that is greater
+  ///         than zero, or -1 if the fork fails.
+  ///     @li \b Child process: zero.
+  //------------------------------------------------------------------
+  lldb::pid_t Fork(char *error_str, size_t error_len);
+
+  //------------------------------------------------------------------
+  /// The master file descriptor accessor.
+  ///
+  /// This object retains ownership of the master file descriptor when
+  /// this accessor is used. Users can call the member function
+  /// PseudoTerminal::ReleaseMasterFileDescriptor() if this
+  /// object should release ownership of the slave file descriptor.
+  ///
+  /// @return
+  ///     The master file descriptor, or PseudoTerminal::invalid_fd
+  ///     if the master file  descriptor is not currently valid.
+  ///
+  /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+  //------------------------------------------------------------------
+  int GetMasterFileDescriptor() const;
+
+  //------------------------------------------------------------------
+  /// The slave file descriptor accessor.
+  ///
+  /// This object retains ownership of the slave file descriptor when
+  /// this accessor is used. Users can call the member function
+  /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this
+  /// object should release ownership of the slave file descriptor.
+  ///
+  /// @return
+  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
+  ///     if the slave file descriptor is not currently valid.
+  ///
+  /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+  //------------------------------------------------------------------
+  int GetSlaveFileDescriptor() const;
+
+  //------------------------------------------------------------------
+  /// Get the name of the slave pseudo terminal.
+  ///
+  /// A master pseudo terminal should already be valid prior to
+  /// calling this function.
+  ///
+  /// @param[out] error
+  ///     An pointer to an error that can describe any errors that
+  ///     occur. This can be NULL if no error status is desired.
+  ///
+  /// @return
+  ///     The name of the slave pseudo terminal as a NULL terminated
+  ///     C. This string that comes from static memory, so a copy of
+  ///     the string should be made as subsequent calls can change
+  ///     this value. NULL is returned if this object doesn't have
+  ///     a valid master pseudo terminal opened or if the call to
+  ///     \c ptsname() fails.
+  ///
+  /// @see PseudoTerminal::OpenFirstAvailableMaster()
+  //------------------------------------------------------------------
+  const char *GetSlaveName(char *error_str, size_t error_len) const;
+
+  //------------------------------------------------------------------
+  /// Open the first available pseudo terminal.
+  ///
+  /// Opens the first available pseudo terminal with \a oflag as the
+  /// permissions. The opened master file descriptor is stored in this
+  /// object and can be accessed by calling the
+  /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients
+  /// can call the PseudoTerminal::ReleaseMasterFileDescriptor()
+  /// accessor function if they wish to use the master file descriptor
+  /// beyond the lifespan of this object.
+  ///
+  /// If this object still has a valid master file descriptor when its
+  /// destructor is called, it will close it.
+  ///
+  /// @param[in] oflag
+  ///     Flags to use when calling \c posix_openpt(\a oflag).
+  ///     A value of "O_RDWR|O_NOCTTY" is suggested.
+  ///
+  /// @param[out] error
+  ///     An pointer to an error that can describe any errors that
+  ///     occur. This can be NULL if no error status is desired.
+  ///
+  /// @return
+  ///     @li \b true when the master files descriptor is
+  ///         successfully opened.
+  ///     @li \b false if anything goes wrong.
+  ///
+  /// @see PseudoTerminal::GetMasterFileDescriptor()
+  /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+  //------------------------------------------------------------------
+  bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);
+
+  //------------------------------------------------------------------
+  /// Open the slave for the current master pseudo terminal.
+  ///
+  /// A master pseudo terminal should already be valid prior to
+  /// calling this function. The opened slave file descriptor is
+  /// stored in this object and can be accessed by calling the
+  /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients
+  /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor()
+  /// accessor function if they wish to use the slave file descriptor
+  /// beyond the lifespan of this object.
+  ///
+  /// If this object still has a valid slave file descriptor when its
+  /// destructor is called, it will close it.
+  ///
+  /// @param[in] oflag
+  ///     Flags to use when calling \c open(\a oflag).
+  ///
+  /// @param[out] error
+  ///     An pointer to an error that can describe any errors that
+  ///     occur. This can be NULL if no error status is desired.
+  ///
+  /// @return
+  ///     @li \b true when the master files descriptor is
+  ///         successfully opened.
+  ///     @li \b false if anything goes wrong.
+  ///
+  /// @see PseudoTerminal::OpenFirstAvailableMaster()
+  /// @see PseudoTerminal::GetSlaveFileDescriptor()
+  /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+  //------------------------------------------------------------------
+  bool OpenSlave(int oflag, char *error_str, size_t error_len);
+
+  //------------------------------------------------------------------
+  /// Release the master file descriptor.
+  ///
+  /// Releases 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.
+  ///
+  /// @return
+  ///     The master file descriptor, or PseudoTerminal::invalid_fd
+  ///     if the mast file descriptor is not currently valid.
+  //------------------------------------------------------------------
+  int ReleaseMasterFileDescriptor();
+
+  //------------------------------------------------------------------
+  /// Release the slave file descriptor.
+  ///
+  /// 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.
+  ///
+  /// @return
+  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
+  ///     if the slave file descriptor is not currently valid.
+  //------------------------------------------------------------------
+  int ReleaseSlaveFileDescriptor();
+
+protected:
+  //------------------------------------------------------------------
+  // Member variables
+  //------------------------------------------------------------------
+  int m_master_fd; ///< The file descriptor for the master.
+  int m_slave_fd;  ///< The file descriptor for the slave.
+
+private:
+  DISALLOW_COPY_AND_ASSIGN(PseudoTerminal);
+};
+
+} // namespace lldb_utility
+
+#endif // #if defined(__cplusplus)
+#endif // #ifndef liblldb_PseudoTerminal_h_
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to