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 
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 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
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   ///     \li \b Parent process: a child process ID that is greater
70   ///         than zero, or -1 if the fork fails.
71   ///     \li \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
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
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   ///     \li \b true when the master files descriptor is
145   ///         successfully opened.
146   ///     \li \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
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   ///     \li \b true when the master files descriptor is
174   ///         successfully opened.
175   ///     \li \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 
206 protected:
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 
211 private:
212   DISALLOW_COPY_AND_ASSIGN(PseudoTerminal);
213 };
214 
215 } // namespace lldb_private
216 
217 #endif // #ifndef liblldb_PseudoTerminal_h_
218