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
20namespace 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//----------------------------------------------------------------------
29class PseudoTerminal
30{
31public:
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
251protected:
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
258private:
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