1//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===//
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
9#ifndef LLDB_HOST_PSEUDOTERMINAL_H
10#define LLDB_HOST_PSEUDOTERMINAL_H
11
12#include <fcntl.h>
13#include <string>
14
15#include "lldb/lldb-defines.h"
16
17namespace lldb_private {
18
19/// \class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h"
20/// A pseudo terminal helper class.
21///
22/// The pseudo terminal class abstracts the use of pseudo terminals on the
23/// host system.
24class PseudoTerminal {
25public:
26  enum {
27    invalid_fd = -1 ///< Invalid file descriptor value
28  };
29
30  /// Default constructor
31  ///
32  /// Constructs this object with invalid master and slave file descriptors.
33  PseudoTerminal();
34
35  /// Destructor
36  ///
37  /// The destructor will close the master and slave file descriptors if they
38  /// are valid and ownership has not been released using one of: @li
39  /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
40  /// PseudoTerminal::ReleaseSaveFileDescriptor()
41  ~PseudoTerminal();
42
43  /// Close the master file descriptor if it is valid.
44  void CloseMasterFileDescriptor();
45
46  /// Close the slave file descriptor if it is valid.
47  void CloseSlaveFileDescriptor();
48
49  /// Fork a child process that uses pseudo terminals for its stdio.
50  ///
51  /// In the parent process, a call to this function results in a pid being
52  /// returned. If the pid is valid, the master file descriptor can be used
53  /// for read/write access to stdio of the child process.
54  ///
55  /// In the child process the stdin/stdout/stderr will already be routed to
56  /// the slave pseudo terminal and the master file descriptor will be closed
57  /// as it is no longer needed by the child process.
58  ///
59  /// This class will close the file descriptors for the master/slave when the
60  /// destructor is called. The file handles can be released using either: @li
61  /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
62  /// PseudoTerminal::ReleaseSaveFileDescriptor()
63  ///
64  /// \param[out] error_str
65  ///     An pointer to an error that can describe any errors that
66  ///     occur. This can be NULL if no error status is desired.
67  ///
68  /// \return
69  ///     \b Parent process: a child process ID that is greater
70  ///         than zero, or -1 if the fork fails.
71  ///     \b Child process: zero.
72  lldb::pid_t Fork(char *error_str, size_t error_len);
73
74  /// The master file descriptor accessor.
75  ///
76  /// This object retains ownership of the master file descriptor when this
77  /// accessor is used. Users can call the member function
78  /// PseudoTerminal::ReleaseMasterFileDescriptor() if this object should
79  /// release ownership of the slave file descriptor.
80  ///
81  /// \return
82  ///     The master file descriptor, or PseudoTerminal::invalid_fd
83  ///     if the master file  descriptor is not currently valid.
84  ///
85  /// \see PseudoTerminal::ReleaseMasterFileDescriptor()
86  int GetMasterFileDescriptor() const;
87
88  /// The slave file descriptor accessor.
89  ///
90  /// This object retains ownership of the slave file descriptor when this
91  /// accessor is used. Users can call the member function
92  /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this object should
93  /// release ownership of the slave file descriptor.
94  ///
95  /// \return
96  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
97  ///     if the slave file descriptor is not currently valid.
98  ///
99  /// \see PseudoTerminal::ReleaseSlaveFileDescriptor()
100  int GetSlaveFileDescriptor() const;
101
102  /// Get the name of the slave pseudo terminal.
103  ///
104  /// A master pseudo terminal should already be valid prior to
105  /// calling this function.
106  ///
107  /// \param[out] error_str
108  ///     An pointer to an error that can describe any errors that
109  ///     occur. This can be NULL if no error status is desired.
110  ///
111  /// \return
112  ///     The name of the slave pseudo terminal as a NULL terminated
113  ///     C. This string that comes from static memory, so a copy of
114  ///     the string should be made as subsequent calls can change
115  ///     this value. NULL is returned if this object doesn't have
116  ///     a valid master pseudo terminal opened or if the call to
117  ///     \c ptsname() fails.
118  ///
119  /// \see PseudoTerminal::OpenFirstAvailableMaster()
120  const char *GetSlaveName(char *error_str, size_t error_len) const;
121
122  /// Open the first available pseudo terminal.
123  ///
124  /// Opens the first available pseudo terminal with \a oflag as the
125  /// permissions. The opened master file descriptor is stored in this object
126  /// and can be accessed by calling the
127  /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients can call the
128  /// PseudoTerminal::ReleaseMasterFileDescriptor() accessor function if they
129  /// wish to use the master file descriptor beyond the lifespan of this
130  /// object.
131  ///
132  /// If this object still has a valid master file descriptor when its
133  /// destructor is called, it will close it.
134  ///
135  /// \param[in] oflag
136  ///     Flags to use when calling \c posix_openpt(\a oflag).
137  ///     A value of "O_RDWR|O_NOCTTY" is suggested.
138  ///
139  /// \param[out] error_str
140  ///     An pointer to an error that can describe any errors that
141  ///     occur. This can be NULL if no error status is desired.
142  ///
143  /// \return
144  ///     \b true when the master files descriptor is
145  ///         successfully opened.
146  ///     \b false if anything goes wrong.
147  ///
148  /// \see PseudoTerminal::GetMasterFileDescriptor() @see
149  /// PseudoTerminal::ReleaseMasterFileDescriptor()
150  bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);
151
152  /// Open the slave for the current master pseudo terminal.
153  ///
154  /// A master pseudo terminal should already be valid prior to
155  /// calling this function. The opened slave file descriptor is stored in
156  /// this object and can be accessed by calling the
157  /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients can call the
158  /// PseudoTerminal::ReleaseSlaveFileDescriptor() accessor function if they
159  /// wish to use the slave file descriptor beyond the lifespan of this
160  /// object.
161  ///
162  /// If this object still has a valid slave file descriptor when its
163  /// destructor is called, it will close it.
164  ///
165  /// \param[in] oflag
166  ///     Flags to use when calling \c open(\a oflag).
167  ///
168  /// \param[out] error_str
169  ///     An pointer to an error that can describe any errors that
170  ///     occur. This can be NULL if no error status is desired.
171  ///
172  /// \return
173  ///     \b true when the master files descriptor is
174  ///         successfully opened.
175  ///     \b false if anything goes wrong.
176  ///
177  /// \see PseudoTerminal::OpenFirstAvailableMaster() @see
178  /// PseudoTerminal::GetSlaveFileDescriptor() @see
179  /// PseudoTerminal::ReleaseSlaveFileDescriptor()
180  bool OpenSlave(int oflag, char *error_str, size_t error_len);
181
182  /// Release the master file descriptor.
183  ///
184  /// Releases ownership of the master pseudo terminal file descriptor without
185  /// closing it. The destructor for this class will close the master file
186  /// descriptor if the ownership isn't released using this call and the
187  /// master file descriptor has been opened.
188  ///
189  /// \return
190  ///     The master file descriptor, or PseudoTerminal::invalid_fd
191  ///     if the mast file descriptor is not currently valid.
192  int ReleaseMasterFileDescriptor();
193
194  /// Release the slave file descriptor.
195  ///
196  /// Release ownership of the slave pseudo terminal file descriptor without
197  /// closing it. The destructor for this class will close the slave file
198  /// descriptor if the ownership isn't released using this call and the slave
199  /// file descriptor has been opened.
200  ///
201  /// \return
202  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
203  ///     if the slave file descriptor is not currently valid.
204  int ReleaseSlaveFileDescriptor();
205
206protected:
207  // Member variables
208  int m_master_fd; ///< The file descriptor for the master.
209  int m_slave_fd;  ///< The file descriptor for the slave.
210
211private:
212  DISALLOW_COPY_AND_ASSIGN(PseudoTerminal);
213};
214
215} // namespace lldb_private
216
217#endif // #ifndef liblldb_PseudoTerminal_h_
218