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