aboutsummaryrefslogtreecommitdiff
path: root/lldb/include/lldb/Host/PseudoTerminal.h
blob: 350f926dcac1e331ccfeb840a67a2d489f8167b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_HOST_PSEUDOTERMINAL_H
#define LLDB_HOST_PSEUDOTERMINAL_H

#include "lldb/lldb-defines.h"
#include "llvm/Support/Error.h"
#include <fcntl.h>
#include <string>

namespace lldb_private {

/// \class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h"
/// 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 primary and secondary file
  /// descriptors.
  PseudoTerminal();

  /// Destructor
  ///
  /// The destructor will close the primary and secondary file descriptors if
  /// they are valid and ownership has not been released using one of: @li
  /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
  /// PseudoTerminal::ReleaseSaveFileDescriptor()
  ~PseudoTerminal();

  /// Close the primary file descriptor if it is valid.
  void ClosePrimaryFileDescriptor();

  /// Close the secondary file descriptor if it is valid.
  void CloseSecondaryFileDescriptor();

  /// 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 primary 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 secondary pseudo terminal and the primary file descriptor will be
  /// closed as it is no longer needed by the child process.
  ///
  /// This class will close the file descriptors for the primary/secondary when
  /// the destructor is called. The file handles can be released using either:
  /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
  /// PseudoTerminal::ReleaseSaveFileDescriptor()
  ///
  /// \return
  ///     \b Parent process: a child process ID that is greater
  ///         than zero, or an error if the fork fails.
  ///     \b Child process: zero.
  llvm::Expected<lldb::pid_t> Fork();

  /// The primary file descriptor accessor.
  ///
  /// This object retains ownership of the primary file descriptor when this
  /// accessor is used. Users can call the member function
  /// PseudoTerminal::ReleasePrimaryFileDescriptor() if this object should
  /// release ownership of the secondary file descriptor.
  ///
  /// \return
  ///     The primary file descriptor, or PseudoTerminal::invalid_fd
  ///     if the primary file  descriptor is not currently valid.
  ///
  /// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
  int GetPrimaryFileDescriptor() const;

  /// The secondary file descriptor accessor.
  ///
  /// This object retains ownership of the secondary file descriptor when this
  /// accessor is used. Users can call the member function
  /// PseudoTerminal::ReleaseSecondaryFileDescriptor() if this object should
  /// release ownership of the secondary file descriptor.
  ///
  /// \return
  ///     The secondary file descriptor, or PseudoTerminal::invalid_fd
  ///     if the secondary file descriptor is not currently valid.
  ///
  /// \see PseudoTerminal::ReleaseSecondaryFileDescriptor()
  int GetSecondaryFileDescriptor() const;

  /// Get the name of the secondary pseudo terminal.
  ///
  /// A primary pseudo terminal should already be valid prior to
  /// calling this function.
  ///
  /// \return
  ///     The name of the secondary pseudo terminal.
  ///
  /// \see PseudoTerminal::OpenFirstAvailablePrimary()
  std::string GetSecondaryName() const;

  /// Open the first available pseudo terminal.
  ///
  /// Opens the first available pseudo terminal with \a oflag as the
  /// permissions. The opened primary file descriptor is stored in this object
  /// and can be accessed by calling the
  /// PseudoTerminal::GetPrimaryFileDescriptor() accessor. Clients can call the
  /// PseudoTerminal::ReleasePrimaryFileDescriptor() accessor function if they
  /// wish to use the primary file descriptor beyond the lifespan of this
  /// object.
  ///
  /// If this object still has a valid primary 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.
  ///
  /// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
  /// PseudoTerminal::ReleasePrimaryFileDescriptor()
  llvm::Error OpenFirstAvailablePrimary(int oflag);

  /// Open the secondary for the current primary pseudo terminal.
  ///
  /// A primary pseudo terminal should already be valid prior to
  /// calling this function. The opened secondary file descriptor is stored in
  /// this object and can be accessed by calling the
  /// PseudoTerminal::GetSecondaryFileDescriptor() accessor. Clients can call
  /// the PseudoTerminal::ReleaseSecondaryFileDescriptor() accessor function if
  /// they wish to use the secondary file descriptor beyond the lifespan of this
  /// object.
  ///
  /// If this object still has a valid secondary file descriptor when its
  /// destructor is called, it will close it.
  ///
  /// \param[in] oflag
  ///     Flags to use when calling \c open(\a oflag).
  ///
  /// \see PseudoTerminal::OpenFirstAvailablePrimary() @see
  /// PseudoTerminal::GetSecondaryFileDescriptor() @see
  /// PseudoTerminal::ReleaseSecondaryFileDescriptor()
  llvm::Error OpenSecondary(int oflag);

  /// Release the primary file descriptor.
  ///
  /// Releases ownership of the primary pseudo terminal file descriptor without
  /// closing it. The destructor for this class will close the primary file
  /// descriptor if the ownership isn't released using this call and the
  /// primary file descriptor has been opened.
  ///
  /// \return
  ///     The primary file descriptor, or PseudoTerminal::invalid_fd
  ///     if the mast file descriptor is not currently valid.
  int ReleasePrimaryFileDescriptor();

  /// Release the secondary file descriptor.
  ///
  /// Release ownership of the secondary pseudo terminal file descriptor without
  /// closing it. The destructor for this class will close the secondary file
  /// descriptor if the ownership isn't released using this call and the
  /// secondary file descriptor has been opened.
  ///
  /// \return
  ///     The secondary file descriptor, or PseudoTerminal::invalid_fd
  ///     if the secondary file descriptor is not currently valid.
  int ReleaseSecondaryFileDescriptor();

protected:
  // Member variables
  int m_primary_fd;   ///< The file descriptor for the primary.
  int m_secondary_fd; ///< The file descriptor for the secondary.

private:
  PseudoTerminal(const PseudoTerminal &) = delete;
  const PseudoTerminal &operator=(const PseudoTerminal &) = delete;
};

} // namespace lldb_private

#endif // LLDB_HOST_PSEUDOTERMINAL_H