LLDB  mainline
PseudoTerminal.cpp
Go to the documentation of this file.
1 //===-- PseudoTerminal.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "lldb/Host/Config.h"
11 #include "llvm/Support/Errc.h"
12 #include "llvm/Support/Errno.h"
13 #include <cassert>
14 #include <limits.h>
15 #include <mutex>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #if defined(TIOCSCTTY)
20 #include <sys/ioctl.h>
21 #endif
22 
23 #include "lldb/Host/PosixApi.h"
24 
25 #if defined(__ANDROID__)
26 int posix_openpt(int flags);
27 #endif
28 
29 using namespace lldb_private;
30 
31 // PseudoTerminal constructor
33  : m_primary_fd(invalid_fd), m_secondary_fd(invalid_fd) {}
34 
35 // Destructor
36 //
37 // The destructor will close the primary and secondary file descriptors if they
38 // are valid and ownership has not been released using the
39 // ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
40 // functions.
44 }
45 
46 // Close the primary file descriptor if it is valid.
48  if (m_primary_fd >= 0) {
49  ::close(m_primary_fd);
51  }
52 }
53 
54 // Close the secondary file descriptor if it is valid.
56  if (m_secondary_fd >= 0) {
57  ::close(m_secondary_fd);
59  }
60 }
61 
63 #if LLDB_ENABLE_POSIX
64  // Open the primary side of a pseudo terminal
66  if (m_primary_fd < 0) {
67  return llvm::errorCodeToError(
68  std::error_code(errno, std::generic_category()));
69  }
70 
71  // Grant access to the secondary pseudo terminal
72  if (::grantpt(m_primary_fd) < 0) {
73  std::error_code EC(errno, std::generic_category());
75  return llvm::errorCodeToError(EC);
76  }
77 
78  // Clear the lock flag on the secondary pseudo terminal
79  if (::unlockpt(m_primary_fd) < 0) {
80  std::error_code EC(errno, std::generic_category());
82  return llvm::errorCodeToError(EC);
83  }
84 
85  return llvm::Error::success();
86 #else
87  return llvm::errorCodeToError(llvm::errc::not_supported);
88 #endif
89 }
90 
93 
95  m_secondary_fd = llvm::sys::RetryAfterSignal(-1, ::open, name.c_str(), oflag);
96  if (m_secondary_fd >= 0)
97  return llvm::Error::success();
98 
99  return llvm::errorCodeToError(
100  std::error_code(errno, std::generic_category()));
101 }
102 
104  assert(m_primary_fd >= 0);
105 #if HAVE_PTSNAME_R
106  char buf[PATH_MAX];
107  buf[0] = '\0';
108  int r = ptsname_r(m_primary_fd, buf, sizeof(buf));
109  (void)r;
110  assert(r == 0);
111  return buf;
112 #else
113  static std::mutex mutex;
114  std::lock_guard<std::mutex> guard(mutex);
115  const char *r = ptsname(m_primary_fd);
116  assert(r != nullptr);
117  return r;
118 #endif
119 }
120 
121 llvm::Expected<lldb::pid_t> PseudoTerminal::Fork() {
122 #if LLDB_ENABLE_POSIX
123  if (llvm::Error Err = OpenFirstAvailablePrimary(O_RDWR | O_CLOEXEC))
124  return std::move(Err);
125 
126  pid_t pid = ::fork();
127  if (pid < 0) {
128  return llvm::errorCodeToError(
129  std::error_code(errno, std::generic_category()));
130  }
131  if (pid > 0) {
132  // Parent process.
133  return pid;
134  }
135 
136  // Child Process
137  ::setsid();
138 
139  if (llvm::Error Err = OpenSecondary(O_RDWR))
140  return std::move(Err);
141 
142  // Primary FD should have O_CLOEXEC set, but let's close it just in
143  // case...
145 
146 #if defined(TIOCSCTTY)
147  // Acquire the controlling terminal
148  if (::ioctl(m_secondary_fd, TIOCSCTTY, (char *)0) < 0) {
149  return llvm::errorCodeToError(
150  std::error_code(errno, std::generic_category()));
151  }
152 #endif
153  // Duplicate all stdio file descriptors to the secondary pseudo terminal
154  for (int fd : {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) {
155  if (::dup2(m_secondary_fd, fd) != fd) {
156  return llvm::errorCodeToError(
157  std::error_code(errno, std::generic_category()));
158  }
159  }
160 #endif
161  return 0;
162 }
163 
164 // The primary file descriptor accessor. This object retains ownership of the
165 // primary file descriptor when this accessor is used. Use
166 // ReleasePrimaryFileDescriptor() if you wish this object to release ownership
167 // of the primary file descriptor.
168 //
169 // Returns the primary file descriptor, or -1 if the primary file descriptor is
170 // not currently valid.
172 
173 // The secondary file descriptor accessor.
174 //
175 // Returns the secondary file descriptor, or -1 if the secondary file descriptor
176 // is not currently valid.
178  return m_secondary_fd;
179 }
180 
181 // Release ownership of the primary pseudo terminal file descriptor without
182 // closing it. The destructor for this class will close the primary file
183 // descriptor if the ownership isn't released using this call and the primary
184 // file descriptor has been opened.
186  // Release ownership of the primary pseudo terminal file descriptor without
187  // closing it. (the destructor for this class will close it otherwise!)
188  int fd = m_primary_fd;
190  return fd;
191 }
192 
193 // Release ownership of the secondary pseudo terminal file descriptor without
194 // closing it. The destructor for this class will close the secondary file
195 // descriptor if the ownership isn't released using this call and the secondary
196 // file descriptor has been opened.
198  // Release ownership of the secondary pseudo terminal file descriptor without
199  // closing it (the destructor for this class will close it otherwise!)
200  int fd = m_secondary_fd;
202  return fd;
203 }
lldb_private::PseudoTerminal::ReleaseSecondaryFileDescriptor
int ReleaseSecondaryFileDescriptor()
Release the secondary file descriptor.
Definition: PseudoTerminal.cpp:197
lldb_private::PseudoTerminal::m_secondary_fd
int m_secondary_fd
The file descriptor for the secondary.
Definition: PseudoTerminal.h:179
lldb_private::PseudoTerminal::GetPrimaryFileDescriptor
int GetPrimaryFileDescriptor() const
The primary file descriptor accessor.
Definition: PseudoTerminal.cpp:171
unlockpt
int unlockpt(int fd)
Definition: windows/PosixApi.h:119
lldb_private::PseudoTerminal::invalid_fd
@ invalid_fd
Invalid file descriptor value.
Definition: PseudoTerminal.h:27
lldb_private::PseudoTerminal::m_primary_fd
int m_primary_fd
The file descriptor for the primary.
Definition: PseudoTerminal.h:178
lldb_private::PseudoTerminal::GetSecondaryFileDescriptor
int GetSecondaryFileDescriptor() const
The secondary file descriptor accessor.
Definition: PseudoTerminal.cpp:177
lldb_private::PseudoTerminal::OpenFirstAvailablePrimary
llvm::Error OpenFirstAvailablePrimary(int oflag)
Open the first available pseudo terminal.
Definition: PseudoTerminal.cpp:62
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:38
lldb_private::PseudoTerminal::OpenSecondary
llvm::Error OpenSecondary(int oflag)
Open the secondary for the current primary pseudo terminal.
Definition: PseudoTerminal.cpp:91
lldb_private::PseudoTerminal::ClosePrimaryFileDescriptor
void ClosePrimaryFileDescriptor()
Close the primary file descriptor if it is valid.
Definition: PseudoTerminal.cpp:47
lldb_private::PseudoTerminal::GetSecondaryName
std::string GetSecondaryName() const
Get the name of the secondary pseudo terminal.
Definition: PseudoTerminal.cpp:103
posix_openpt
int posix_openpt(int flag)
Definition: windows/PosixApi.h:113
lldb_private::PseudoTerminal::ReleasePrimaryFileDescriptor
int ReleasePrimaryFileDescriptor()
Release the primary file descriptor.
Definition: PseudoTerminal.cpp:185
lldb_private::PseudoTerminal::CloseSecondaryFileDescriptor
void CloseSecondaryFileDescriptor()
Close the secondary file descriptor if it is valid.
Definition: PseudoTerminal.cpp:55
lldb_private::PseudoTerminal::PseudoTerminal
PseudoTerminal()
Default constructor.
Definition: PseudoTerminal.cpp:32
setsid
pid_t setsid(void)
Definition: windows/PosixApi.h:124
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::PseudoTerminal::~PseudoTerminal
~PseudoTerminal()
Destructor.
Definition: PseudoTerminal.cpp:41
PseudoTerminal.h
lldb_private::PseudoTerminal::Fork
llvm::Expected< lldb::pid_t > Fork()
Fork a child process that uses pseudo terminals for its stdio.
Definition: PseudoTerminal.cpp:121
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
ptsname
char * ptsname(int fd)
Definition: windows/PosixApi.h:121
fork
pid_t fork(void)
Definition: windows/PosixApi.h:123
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
PosixApi.h
grantpt
int grantpt(int fd)
Definition: windows/PosixApi.h:120
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25