Repository: bitcoin/bitcoin
File: src/util/subprocess.h (C/C++)

Code before:
  FILE* input()  { return input_.get(); }
  FILE* output() { return output_.get(); }
  FILE* error()  { return error_.get(); }

  void input(FILE* fp)  { input_.reset(fp, fclose); }
  void output(FILE* fp) { output_.reset(fp, fclose); }
  void error(FILE* fp)  { error_.reset(fp, fclose); }

  void set_out_buf_cap(size_t cap) { comm_.set_out_buf_cap(cap); }
  void set_err_buf_cap(size_t cap) { comm_.set_err_buf_cap(cap); }

public: /* Communication forwarding API's */
  int send(const char* msg, size_t length)
  { return comm_.send(msg, length); }

  int send(const std::vector<char>& msg)
  { return comm_.send(msg); }

  std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
  { return comm_.communicate(msg, length); }

  std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
  { return comm_.communicate(msg); }


public:// Yes they are public

  std::shared_ptr<FILE> input_  = nullptr;
  std::shared_ptr<FILE> output_ = nullptr;
  std::shared_ptr<FILE> error_  = nullptr;

#ifdef __USING_WINDOWS__
  HANDLE g_hChildStd_IN_Rd = nullptr;
  HANDLE g_hChildStd_IN_Wr = nullptr;
  HANDLE g_hChildStd_OUT_Rd = nullptr;
  HANDLE g_hChildStd_OUT_Wr = nullptr;
  HANDLE g_hChildStd_ERR_Rd = nullptr;
  HANDLE g_hChildStd_ERR_Wr = nullptr;
#endif

  // Pipes for communicating with child

  // Emulates stdin
  int write_to_child_   = -1; // Parent owned descriptor
  int read_from_parent_ = -1; // Child owned descriptor

  // Emulates stdout
  int write_to_parent_ = -1; // Child owned descriptor
  int read_from_child_ = -1; // Parent owned descriptor

  // Emulates stderr

Review comment (suggestion):
The numbering of this list is off after this change. That might be confusing to someone in the future. I would suggest either updating the following numbering or something like.

```
 * 6. (deleted)
 * 7. (deleted)
```

Code after:
  int err_read_  = -1; // Read error from child (Parent owned)

private:
  Communication comm_;
};

} // end namespace detail



/*!
 * class: Popen
 * This is the single most important class in the whole library
 * and glues together all the helper classes to provide a common
 * interface to the client.
 *
 * API's provided by the class:
 * Popen({"cmd"}, output{..}, error{..}, ....)
 *    Command provided as a sequence.
 * Popen("cmd arg1", output{..}, error{..}, ....)
 *    Command provided in a single string.
 * wait()             - Wait for the child to exit.
 * retcode()          - The return code of the exited child.
 * pid()              - PID of the spawned child.
 * poll()             - Check the status of the running child.
 * send(...)          - Send input to the input channel of the child.
 * communicate(...)   - Get the output/error from the child and close the channels
 *                      from the parent side.
 * input()            - Get the input channel/File pointer. Can be used for
 *                      customizing the way of sending input to child.
 * output()           - Get the output channel/File pointer. Usually used
                        in case of redirection. See piping examples.
 * error()            - Get the error channel/File pointer. Usually used
                        in case of redirection.
 */
class Popen
{
public:
  friend struct detail::ArgumentDeducer;
  friend class detail::Child;

  template <typename... Args>
  Popen(const std::string& cmd_args, Args&& ...args):
    args_(cmd_args)
  {
    vargs_ = util::split(cmd_args);
    init_args(std::forward<Args>(args)...);

    // Setup the communication channels of the Popen class
    stream_.setup_comm_channels();