reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
//===-- PseudoTerminal.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_HOST_PSEUDOTERMINAL_H
#define LLDB_HOST_PSEUDOTERMINAL_H

#include <fcntl.h>
#include <string>

#include "lldb/lldb-defines.h"

namespace lldb_private {

/// \class PseudoTerminal PseudoTerminal.h "lldb/Host/PseudoTerminal.h"
/// A pseudo terminal helper class.
///
/// The pseudo terminal class abstracts the use of pseudo terminals on the
/// host system.
class PseudoTerminal {
public:
  enum {
    invalid_fd = -1 ///< Invalid file descriptor value
  };

  /// Default constructor
  ///
  /// Constructs this object with invalid master and slave file descriptors.
  PseudoTerminal();

  /// Destructor
  ///
  /// The destructor will close the master and slave file descriptors if they
  /// are valid and ownership has not been released using one of: @li
  /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
  /// PseudoTerminal::ReleaseSaveFileDescriptor()
  ~PseudoTerminal();

  /// Close the master file descriptor if it is valid.
  void CloseMasterFileDescriptor();

  /// Close the slave file descriptor if it is valid.
  void CloseSlaveFileDescriptor();

  /// Fork a child process that uses pseudo terminals for its stdio.
  ///
  /// In the parent process, a call to this function results in a pid being
  /// returned. If the pid is valid, the master file descriptor can be used
  /// for read/write access to stdio of the child process.
  ///
  /// In the child process the stdin/stdout/stderr will already be routed to
  /// the slave pseudo terminal and the master file descriptor will be closed
  /// as it is no longer needed by the child process.
  ///
  /// This class will close the file descriptors for the master/slave when the
  /// destructor is called. The file handles can be released using either: @li
  /// PseudoTerminal::ReleaseMasterFileDescriptor() @li
  /// PseudoTerminal::ReleaseSaveFileDescriptor()
  ///
  /// \param[out] error
  ///     An pointer to an error that can describe any errors that
  ///     occur. This can be NULL if no error status is desired.
  ///
  /// \return
  ///     \li \b Parent process: a child process ID that is greater
  ///         than zero, or -1 if the fork fails.
  ///     \li \b Child process: zero.
  lldb::pid_t Fork(char *error_str, size_t error_len);

  /// The master file descriptor accessor.
  ///
  /// This object retains ownership of the master file descriptor when this
  /// accessor is used. Users can call the member function
  /// PseudoTerminal::ReleaseMasterFileDescriptor() if this object should
  /// release ownership of the slave file descriptor.
  ///
  /// \return
  ///     The master file descriptor, or PseudoTerminal::invalid_fd
  ///     if the master file  descriptor is not currently valid.
  ///
  /// \see PseudoTerminal::ReleaseMasterFileDescriptor()
  int GetMasterFileDescriptor() const;

  /// The slave file descriptor accessor.
  ///
  /// This object retains ownership of the slave file descriptor when this
  /// accessor is used. Users can call the member function
  /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this object should
  /// release ownership of the slave file descriptor.
  ///
  /// \return
  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
  ///     if the slave file descriptor is not currently valid.
  ///
  /// \see PseudoTerminal::ReleaseSlaveFileDescriptor()
  int GetSlaveFileDescriptor() const;

  /// Get the name of the slave pseudo terminal.
  ///
  /// A master pseudo terminal should already be valid prior to
  /// calling this function.
  ///
  /// \param[out] error
  ///     An pointer to an error that can describe any errors that
  ///     occur. This can be NULL if no error status is desired.
  ///
  /// \return
  ///     The name of the slave pseudo terminal as a NULL terminated
  ///     C. This string that comes from static memory, so a copy of
  ///     the string should be made as subsequent calls can change
  ///     this value. NULL is returned if this object doesn't have
  ///     a valid master pseudo terminal opened or if the call to
  ///     \c ptsname() fails.
  ///
  /// \see PseudoTerminal::OpenFirstAvailableMaster()
  const char *GetSlaveName(char *error_str, size_t error_len) const;

  /// Open the first available pseudo terminal.
  ///
  /// Opens the first available pseudo terminal with \a oflag as the
  /// permissions. The opened master file descriptor is stored in this object
  /// and can be accessed by calling the
  /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients can call the
  /// PseudoTerminal::ReleaseMasterFileDescriptor() accessor function if they
  /// wish to use the master file descriptor beyond the lifespan of this
  /// object.
  ///
  /// If this object still has a valid master file descriptor when its
  /// destructor is called, it will close it.
  ///
  /// \param[in] oflag
  ///     Flags to use when calling \c posix_openpt(\a oflag).
  ///     A value of "O_RDWR|O_NOCTTY" is suggested.
  ///
  /// \param[out] error
  ///     An pointer to an error that can describe any errors that
  ///     occur. This can be NULL if no error status is desired.
  ///
  /// \return
  ///     \li \b true when the master files descriptor is
  ///         successfully opened.
  ///     \li \b false if anything goes wrong.
  ///
  /// \see PseudoTerminal::GetMasterFileDescriptor() @see
  /// PseudoTerminal::ReleaseMasterFileDescriptor()
  bool OpenFirstAvailableMaster(int oflag, char *error_str, size_t error_len);

  /// Open the slave for the current master pseudo terminal.
  ///
  /// A master pseudo terminal should already be valid prior to
  /// calling this function. The opened slave file descriptor is stored in
  /// this object and can be accessed by calling the
  /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients can call the
  /// PseudoTerminal::ReleaseSlaveFileDescriptor() accessor function if they
  /// wish to use the slave file descriptor beyond the lifespan of this
  /// object.
  ///
  /// If this object still has a valid slave file descriptor when its
  /// destructor is called, it will close it.
  ///
  /// \param[in] oflag
  ///     Flags to use when calling \c open(\a oflag).
  ///
  /// \param[out] error
  ///     An pointer to an error that can describe any errors that
  ///     occur. This can be NULL if no error status is desired.
  ///
  /// \return
  ///     \li \b true when the master files descriptor is
  ///         successfully opened.
  ///     \li \b false if anything goes wrong.
  ///
  /// \see PseudoTerminal::OpenFirstAvailableMaster() @see
  /// PseudoTerminal::GetSlaveFileDescriptor() @see
  /// PseudoTerminal::ReleaseSlaveFileDescriptor()
  bool OpenSlave(int oflag, char *error_str, size_t error_len);

  /// Release the master file descriptor.
  ///
  /// Releases ownership of the master pseudo terminal file descriptor without
  /// closing it. The destructor for this class will close the master file
  /// descriptor if the ownership isn't released using this call and the
  /// master file descriptor has been opened.
  ///
  /// \return
  ///     The master file descriptor, or PseudoTerminal::invalid_fd
  ///     if the mast file descriptor is not currently valid.
  int ReleaseMasterFileDescriptor();

  /// Release the slave file descriptor.
  ///
  /// Release ownership of the slave pseudo terminal file descriptor without
  /// closing it. The destructor for this class will close the slave file
  /// descriptor if the ownership isn't released using this call and the slave
  /// file descriptor has been opened.
  ///
  /// \return
  ///     The slave file descriptor, or PseudoTerminal::invalid_fd
  ///     if the slave file descriptor is not currently valid.
  int ReleaseSlaveFileDescriptor();

protected:
  // Member variables
  int m_master_fd; ///< The file descriptor for the master.
  int m_slave_fd;  ///< The file descriptor for the slave.

private:
  DISALLOW_COPY_AND_ASSIGN(PseudoTerminal);
};

} // namespace lldb_private

#endif // #ifndef liblldb_PseudoTerminal_h_