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 "lldb/lldb-defines.h"
13 #include "llvm/Support/Error.h"
14 #include <fcntl.h>
15 #include <string>
16 
17 namespace 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.
24 class PseudoTerminal {
25 public:
26   enum {
27     invalid_fd = -1 ///< Invalid file descriptor value
28   };
29 
30   /// Default constructor
31   ///
32   /// Constructs this object with invalid primary and secondary file
33   /// descriptors.
34   PseudoTerminal();
35 
36   /// Destructor
37   ///
38   /// The destructor will close the primary and secondary file descriptors if
39   /// they are valid and ownership has not been released using one of: @li
40   /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
41   /// PseudoTerminal::ReleaseSaveFileDescriptor()
42   ~PseudoTerminal();
43 
44   /// Close the primary file descriptor if it is valid.
45   void ClosePrimaryFileDescriptor();
46 
47   /// Close the secondary file descriptor if it is valid.
48   void CloseSecondaryFileDescriptor();
49 
50   /// Fork a child process that uses pseudo terminals for its stdio.
51   ///
52   /// In the parent process, a call to this function results in a pid being
53   /// returned. If the pid is valid, the primary file descriptor can be used
54   /// for read/write access to stdio of the child process.
55   ///
56   /// In the child process the stdin/stdout/stderr will already be routed to
57   /// the secondary pseudo terminal and the primary file descriptor will be
58   /// closed as it is no longer needed by the child process.
59   ///
60   /// This class will close the file descriptors for the primary/secondary when
61   /// the destructor is called. The file handles can be released using either:
62   /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
63   /// PseudoTerminal::ReleaseSaveFileDescriptor()
64   ///
65   /// \return
66   ///     \b Parent process: a child process ID that is greater
67   ///         than zero, or an error if the fork fails.
68   ///     \b Child process: zero.
69   llvm::Expected<lldb::pid_t> Fork();
70 
71   /// The primary file descriptor accessor.
72   ///
73   /// This object retains ownership of the primary file descriptor when this
74   /// accessor is used. Users can call the member function
75   /// PseudoTerminal::ReleasePrimaryFileDescriptor() if this object should
76   /// release ownership of the secondary file descriptor.
77   ///
78   /// \return
79   ///     The primary file descriptor, or PseudoTerminal::invalid_fd
80   ///     if the primary file  descriptor is not currently valid.
81   ///
82   /// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
83   int GetPrimaryFileDescriptor() const;
84 
85   /// The secondary file descriptor accessor.
86   ///
87   /// This object retains ownership of the secondary file descriptor when this
88   /// accessor is used. Users can call the member function
89   /// PseudoTerminal::ReleaseSecondaryFileDescriptor() if this object should
90   /// release ownership of the secondary file descriptor.
91   ///
92   /// \return
93   ///     The secondary file descriptor, or PseudoTerminal::invalid_fd
94   ///     if the secondary file descriptor is not currently valid.
95   ///
96   /// \see PseudoTerminal::ReleaseSecondaryFileDescriptor()
97   int GetSecondaryFileDescriptor() const;
98 
99   /// Get the name of the secondary pseudo terminal.
100   ///
101   /// A primary pseudo terminal should already be valid prior to
102   /// calling this function.
103   ///
104   /// \return
105   ///     The name of the secondary pseudo terminal.
106   ///
107   /// \see PseudoTerminal::OpenFirstAvailablePrimary()
108   std::string GetSecondaryName() const;
109 
110   /// Open the first available pseudo terminal.
111   ///
112   /// Opens the first available pseudo terminal with \a oflag as the
113   /// permissions. The opened primary file descriptor is stored in this object
114   /// and can be accessed by calling the
115   /// PseudoTerminal::GetPrimaryFileDescriptor() accessor. Clients can call the
116   /// PseudoTerminal::ReleasePrimaryFileDescriptor() accessor function if they
117   /// wish to use the primary file descriptor beyond the lifespan of this
118   /// object.
119   ///
120   /// If this object still has a valid primary file descriptor when its
121   /// destructor is called, it will close it.
122   ///
123   /// \param[in] oflag
124   ///     Flags to use when calling \c posix_openpt(\a oflag).
125   ///     A value of "O_RDWR|O_NOCTTY" is suggested.
126   ///
127   /// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
128   /// PseudoTerminal::ReleasePrimaryFileDescriptor()
129   llvm::Error OpenFirstAvailablePrimary(int oflag);
130 
131   /// Open the secondary for the current primary pseudo terminal.
132   ///
133   /// A primary pseudo terminal should already be valid prior to
134   /// calling this function. The opened secondary file descriptor is stored in
135   /// this object and can be accessed by calling the
136   /// PseudoTerminal::GetSecondaryFileDescriptor() accessor. Clients can call
137   /// the PseudoTerminal::ReleaseSecondaryFileDescriptor() accessor function if
138   /// they wish to use the secondary file descriptor beyond the lifespan of this
139   /// object.
140   ///
141   /// If this object still has a valid secondary file descriptor when its
142   /// destructor is called, it will close it.
143   ///
144   /// \param[in] oflag
145   ///     Flags to use when calling \c open(\a oflag).
146   ///
147   /// \see PseudoTerminal::OpenFirstAvailablePrimary() @see
148   /// PseudoTerminal::GetSecondaryFileDescriptor() @see
149   /// PseudoTerminal::ReleaseSecondaryFileDescriptor()
150   llvm::Error OpenSecondary(int oflag);
151 
152   /// Release the primary file descriptor.
153   ///
154   /// Releases ownership of the primary pseudo terminal file descriptor without
155   /// closing it. The destructor for this class will close the primary file
156   /// descriptor if the ownership isn't released using this call and the
157   /// primary file descriptor has been opened.
158   ///
159   /// \return
160   ///     The primary file descriptor, or PseudoTerminal::invalid_fd
161   ///     if the mast file descriptor is not currently valid.
162   int ReleasePrimaryFileDescriptor();
163 
164   /// Release the secondary file descriptor.
165   ///
166   /// Release ownership of the secondary pseudo terminal file descriptor without
167   /// closing it. The destructor for this class will close the secondary file
168   /// descriptor if the ownership isn't released using this call and the
169   /// secondary file descriptor has been opened.
170   ///
171   /// \return
172   ///     The secondary file descriptor, or PseudoTerminal::invalid_fd
173   ///     if the secondary file descriptor is not currently valid.
174   int ReleaseSecondaryFileDescriptor();
175 
176 protected:
177   // Member variables
178   int m_primary_fd = invalid_fd;   ///< The file descriptor for the primary.
179   int m_secondary_fd = invalid_fd; ///< The file descriptor for the secondary.
180 
181 private:
182   PseudoTerminal(const PseudoTerminal &) = delete;
183   const PseudoTerminal &operator=(const PseudoTerminal &) = delete;
184 };
185 
186 } // namespace lldb_private
187 
188 #endif // LLDB_HOST_PSEUDOTERMINAL_H
189