PStreams
pstream.h
Go to the documentation of this file.
1 // PStreams - POSIX Process I/O for C++
2 
3 // Copyright (C) 2001 - 2017 Jonathan Wakely
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
18 #ifndef REDI_PSTREAM_H_SEEN
19 #define REDI_PSTREAM_H_SEEN
20 
21 #include <ios>
22 #include <streambuf>
23 #include <istream>
24 #include <ostream>
25 #include <string>
26 #include <vector>
27 #include <algorithm> // for min()
28 #include <cerrno> // for errno
29 #include <cstddef> // for size_t, NULL
30 #include <cstdlib> // for exit()
31 #include <sys/types.h> // for pid_t
32 #include <sys/wait.h> // for waitpid()
33 #include <sys/ioctl.h> // for ioctl() and FIONREAD
34 #if defined(__sun)
35 # include <sys/filio.h> // for FIONREAD on Solaris 2.5
36 #endif
37 #include <unistd.h> // for pipe() fork() exec() and filedes functions
38 #include <signal.h> // for kill()
39 #include <fcntl.h> // for fcntl()
40 #if REDI_EVISCERATE_PSTREAMS
41 # include <stdio.h> // for FILE, fdopen()
42 #endif
43 
44 
46 #define PSTREAMS_VERSION 0x0101 // 1.0.1
47 
61 namespace redi
62 {
64  struct pstreams
65  {
67  typedef std::ios_base::openmode pmode;
68 
70  typedef std::vector<std::string> argv_type;
71 
73  typedef int fd_type;
74 
75  static const pmode pstdin = std::ios_base::out;
76  static const pmode pstdout = std::ios_base::in;
77  static const pmode pstderr = std::ios_base::app;
78 
80  static const pmode newpg = std::ios_base::trunc;
81 
82  protected:
83  enum { bufsz = 32 };
84  enum { pbsz = 2 };
85  };
86 
88  template <typename CharT, typename Traits = std::char_traits<CharT> >
90  : public std::basic_streambuf<CharT, Traits>
91  , public pstreams
92  {
93  public:
94  // Type definitions for dependent types
95  typedef CharT char_type;
96  typedef Traits traits_type;
97  typedef typename traits_type::int_type int_type;
98  typedef typename traits_type::off_type off_type;
99  typedef typename traits_type::pos_type pos_type;
101  typedef fd_type fd_t;
102 
105 
107  basic_pstreambuf(const std::string& cmd, pmode mode);
108 
110  basic_pstreambuf( const std::string& file,
111  const argv_type& argv,
112  pmode mode );
113 
115  ~basic_pstreambuf();
116 
119  open(const std::string& cmd, pmode mode);
120 
123  open(const std::string& file, const argv_type& argv, pmode mode);
124 
127  close();
128 
131  kill(int signal = SIGTERM);
132 
135  killpg(int signal = SIGTERM);
136 
138  void
139  peof();
140 
142  bool
143  read_err(bool readerr = true);
144 
146  bool
147  is_open() const;
148 
150  bool
151  exited();
152 
153 #if REDI_EVISCERATE_PSTREAMS
154  std::size_t
156  fopen(FILE*& in, FILE*& out, FILE*& err);
157 #endif
158 
160  int
161  status() const;
162 
164  int
165  error() const;
166 
167  protected:
169  int_type
170  overflow(int_type c);
171 
173  int_type
174  underflow();
175 
177  int_type
178  pbackfail(int_type c = traits_type::eof());
179 
181  int
182  sync();
183 
185  std::streamsize
186  xsputn(const char_type* s, std::streamsize n);
187 
189  std::streamsize
190  write(const char_type* s, std::streamsize n);
191 
193  std::streamsize
194  read(char_type* s, std::streamsize n);
195 
197  std::streamsize
198  showmanyc();
199 
200  protected:
202  enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
203 
205  pid_t
206  fork(pmode mode);
207 
209  int
210  wait(bool nohang = false);
211 
213  fd_type&
214  wpipe();
215 
217  fd_type&
218  rpipe();
219 
221  fd_type&
222  rpipe(buf_read_src which);
223 
224  void
225  create_buffers(pmode mode);
226 
227  void
228  destroy_buffers(pmode mode);
229 
231  bool
232  empty_buffer();
233 
234  bool
235  fill_buffer(bool non_blocking = false);
236 
238  char_type*
239  rbuffer();
240 
242  switch_read_buffer(buf_read_src);
243 
244  private:
246  basic_pstreambuf& operator=(const basic_pstreambuf&);
247 
248  void
249  init_rbuffers();
250 
251  pid_t ppid_; // pid of process
252  fd_type wpipe_; // pipe used to write to process' stdin
253  fd_type rpipe_[2]; // two pipes to read from, stdout and stderr
254  char_type* wbuffer_;
255  char_type* rbuffer_[2];
256  char_type* rbufstate_[3];
258  buf_read_src rsrc_;
259  int status_; // hold exit status of child process
260  int error_; // hold errno if fork() or exec() fails
261  };
262 
264  template <typename CharT, typename Traits = std::char_traits<CharT> >
266  : virtual public std::basic_ios<CharT, Traits>
267  , virtual public pstreams
268  {
269  protected:
271 
272  typedef pstreams::pmode pmode;
274 
276  pstream_common();
277 
279  pstream_common(const std::string& cmd, pmode mode);
280 
282  pstream_common(const std::string& file, const argv_type& argv, pmode mode);
283 
285  virtual
286  ~pstream_common() = 0;
287 
289  void
290  do_open(const std::string& cmd, pmode mode);
291 
293  void
294  do_open(const std::string& file, const argv_type& argv, pmode mode);
295 
296  public:
298  void
299  close();
300 
302  bool
303  is_open() const;
304 
306  const std::string&
307  command() const;
308 
310  streambuf_type*
311  rdbuf() const;
312 
313 #if REDI_EVISCERATE_PSTREAMS
314  std::size_t
316  fopen(FILE*& in, FILE*& out, FILE*& err);
317 #endif
318 
319  protected:
320  std::string command_;
321  streambuf_type buf_;
322  };
323 
324 
335  template <typename CharT, typename Traits = std::char_traits<CharT> >
337  : public std::basic_istream<CharT, Traits>
338  , public pstream_common<CharT, Traits>
339  , virtual public pstreams
340  {
341  typedef std::basic_istream<CharT, Traits> istream_type;
343 
344  using pbase_type::buf_; // declare name in this scope
345 
346  // Ensure a basic_ipstream will read from at least one pipe
347  pmode readable(pmode mode)
348  {
349  if (!(mode & (pstdout|pstderr)))
350  mode |= pstdout;
351  return mode;
352  }
353 
354  public:
356  typedef typename pbase_type::pmode pmode;
357 
359  typedef typename pbase_type::argv_type argv_type;
360 
363  : istream_type(NULL), pbase_type()
364  { }
365 
376  explicit
377  basic_ipstream(const std::string& cmd, pmode mode = pstdout)
378  : istream_type(NULL), pbase_type(cmd, readable(mode))
379  { }
380 
392  basic_ipstream( const std::string& file,
393  const argv_type& argv,
394  pmode mode = pstdout )
395  : istream_type(NULL), pbase_type(file, argv, readable(mode))
396  { }
397 
408  explicit
409  basic_ipstream(const argv_type& argv, pmode mode = pstdout)
410  : istream_type(NULL), pbase_type(argv.at(0), argv, readable(mode))
411  { }
412 
413 #if __cplusplus >= 201103L
414  template<typename T>
415  explicit
416  basic_ipstream(std::initializer_list<T> args, pmode mode = pstdout)
417  : basic_ipstream(argv_type(args.begin(), args.end()), mode)
418  { }
419 #endif
420 
427  { }
428 
438  void
439  open(const std::string& cmd, pmode mode = pstdout)
440  {
441  this->do_open(cmd, readable(mode));
442  }
443 
454  void
455  open( const std::string& file,
456  const argv_type& argv,
457  pmode mode = pstdout )
458  {
459  this->do_open(file, argv, readable(mode));
460  }
461 
467  out()
468  {
469  this->buf_.read_err(false);
470  return *this;
471  }
472 
478  err()
479  {
480  this->buf_.read_err(true);
481  return *this;
482  }
483  };
484 
485 
495  template <typename CharT, typename Traits = std::char_traits<CharT> >
497  : public std::basic_ostream<CharT, Traits>
498  , public pstream_common<CharT, Traits>
499  , virtual public pstreams
500  {
501  typedef std::basic_ostream<CharT, Traits> ostream_type;
503 
504  using pbase_type::buf_; // declare name in this scope
505 
506  public:
508  typedef typename pbase_type::pmode pmode;
509 
511  typedef typename pbase_type::argv_type argv_type;
512 
515  : ostream_type(NULL), pbase_type()
516  { }
517 
528  explicit
529  basic_opstream(const std::string& cmd, pmode mode = pstdin)
530  : ostream_type(NULL), pbase_type(cmd, mode|pstdin)
531  { }
532 
544  basic_opstream( const std::string& file,
545  const argv_type& argv,
546  pmode mode = pstdin )
547  : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
548  { }
549 
560  explicit
561  basic_opstream(const argv_type& argv, pmode mode = pstdin)
562  : ostream_type(NULL), pbase_type(argv.at(0), argv, mode|pstdin)
563  { }
564 
565 #if __cplusplus >= 201103L
566 
573  template<typename T>
574  explicit
575  basic_opstream(std::initializer_list<T> args, pmode mode = pstdin)
576  : basic_opstream(argv_type(args.begin(), args.end()), mode)
577  { }
578 #endif
579 
586 
596  void
597  open(const std::string& cmd, pmode mode = pstdin)
598  {
599  this->do_open(cmd, mode|pstdin);
600  }
601 
612  void
613  open( const std::string& file,
614  const argv_type& argv,
615  pmode mode = pstdin)
616  {
617  this->do_open(file, argv, mode|pstdin);
618  }
619  };
620 
621 
635  template <typename CharT, typename Traits = std::char_traits<CharT> >
637  : public std::basic_iostream<CharT, Traits>
638  , public pstream_common<CharT, Traits>
639  , virtual public pstreams
640  {
641  typedef std::basic_iostream<CharT, Traits> iostream_type;
643 
644  using pbase_type::buf_; // declare name in this scope
645 
646  public:
648  typedef typename pbase_type::pmode pmode;
649 
651  typedef typename pbase_type::argv_type argv_type;
652 
655  : iostream_type(NULL), pbase_type()
656  { }
657 
668  explicit
669  basic_pstream(const std::string& cmd, pmode mode = pstdout|pstdin)
670  : iostream_type(NULL), pbase_type(cmd, mode)
671  { }
672 
684  basic_pstream( const std::string& file,
685  const argv_type& argv,
686  pmode mode = pstdout|pstdin )
687  : iostream_type(NULL), pbase_type(file, argv, mode)
688  { }
689 
700  explicit
701  basic_pstream(const argv_type& argv, pmode mode = pstdout|pstdin)
702  : iostream_type(NULL), pbase_type(argv.at(0), argv, mode)
703  { }
704 
705 #if __cplusplus >= 201103L
706 
713  template<typename T>
714  explicit
715  basic_pstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
716  : basic_pstream(argv_type(l.begin(), l.end()), mode)
717  { }
718 #endif
719 
726 
736  void
737  open(const std::string& cmd, pmode mode = pstdout|pstdin)
738  {
739  this->do_open(cmd, mode);
740  }
741 
752  void
753  open( const std::string& file,
754  const argv_type& argv,
755  pmode mode = pstdout|pstdin )
756  {
757  this->do_open(file, argv, mode);
758  }
759 
765  out()
766  {
767  this->buf_.read_err(false);
768  return *this;
769  }
770 
776  err()
777  {
778  this->buf_.read_err(true);
779  return *this;
780  }
781  };
782 
783 
805  template <typename CharT, typename Traits = std::char_traits<CharT> >
807  : public std::basic_ostream<CharT, Traits>
808  , private std::basic_istream<CharT, Traits>
809  , private pstream_common<CharT, Traits>
810  , virtual public pstreams
811  {
812  typedef std::basic_ostream<CharT, Traits> ostream_type;
813  typedef std::basic_istream<CharT, Traits> istream_type;
815 
816  using pbase_type::buf_; // declare name in this scope
817 
818  public:
820  typedef typename pbase_type::pmode pmode;
821 
823  typedef typename pbase_type::argv_type argv_type;
824 
827  : ostream_type(NULL), istream_type(NULL), pbase_type()
828  { }
829 
840  explicit
841  basic_rpstream(const std::string& cmd, pmode mode = pstdout|pstdin)
842  : ostream_type(NULL) , istream_type(NULL) , pbase_type(cmd, mode)
843  { }
844 
856  basic_rpstream( const std::string& file,
857  const argv_type& argv,
858  pmode mode = pstdout|pstdin )
859  : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
860  { }
861 
872  explicit
873  basic_rpstream(const argv_type& argv, pmode mode = pstdout|pstdin)
874  : ostream_type(NULL), istream_type(NULL),
875  pbase_type(argv.at(0), argv, mode)
876  { }
877 
878 #if __cplusplus >= 201103L
879 
886  template<typename T>
887  explicit
888  basic_rpstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
889  : basic_rpstream(argv_type(l.begin(), l.end()), mode)
890  { }
891 #endif
892 
895 
905  void
906  open(const std::string& cmd, pmode mode = pstdout|pstdin)
907  {
908  this->do_open(cmd, mode);
909  }
910 
921  void
922  open( const std::string& file,
923  const argv_type& argv,
924  pmode mode = pstdout|pstdin )
925  {
926  this->do_open(file, argv, mode);
927  }
928 
934  istream_type&
935  out()
936  {
937  this->buf_.read_err(false);
938  return *this;
939  }
940 
946  istream_type&
947  err()
948  {
949  this->buf_.read_err(true);
950  return *this;
951  }
952  };
953 
954 
965 
966 
979  template <typename C, typename T>
980  inline std::basic_ostream<C,T>&
981  peof(std::basic_ostream<C,T>& s)
982  {
983  typedef basic_pstreambuf<C,T> pstreambuf_type;
984  if (pstreambuf_type* p = dynamic_cast<pstreambuf_type*>(s.rdbuf()))
985  p->peof();
986  return s;
987  }
988 
989 
990  /*
991  * member definitions for pstreambuf
992  */
993 
994 
1001  template <typename C, typename T>
1002  inline
1004  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1005  , wpipe_(-1)
1006  , wbuffer_(NULL)
1007  , rsrc_(rsrc_out)
1008  , status_(-1)
1009  , error_(0)
1010  {
1011  init_rbuffers();
1012  }
1013 
1022  template <typename C, typename T>
1023  inline
1024  basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& cmd, pmode mode)
1025  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1026  , wpipe_(-1)
1027  , wbuffer_(NULL)
1028  , rsrc_(rsrc_out)
1029  , status_(-1)
1030  , error_(0)
1031  {
1032  init_rbuffers();
1033  open(cmd, mode);
1034  }
1035 
1045  template <typename C, typename T>
1046  inline
1048  const argv_type& argv,
1049  pmode mode )
1050  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1051  , wpipe_(-1)
1052  , wbuffer_(NULL)
1053  , rsrc_(rsrc_out)
1054  , status_(-1)
1055  , error_(0)
1056  {
1057  init_rbuffers();
1058  open(file, argv, mode);
1059  }
1060 
1065  template <typename C, typename T>
1066  inline
1068  {
1069  close();
1070  }
1071 
1099  template <typename C, typename T>
1101  basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
1102  {
1103  const char * shell_path = "/bin/sh";
1104 #if 0
1105  const std::string argv[] = { "sh", "-c", command };
1106  return this->open(shell_path, argv_type(argv, argv+3), mode);
1107 #else
1108  basic_pstreambuf<C,T>* ret = NULL;
1109 
1110  if (!is_open())
1111  {
1112  switch(fork(mode))
1113  {
1114  case 0 :
1115  // this is the new process, exec command
1116  ::execl(shell_path, "sh", "-c", command.c_str(), (char*)NULL);
1117 
1118  // can only reach this point if exec() failed
1119 
1120  // parent can get exit code from waitpid()
1121  ::_exit(errno);
1122  // using std::exit() would make static dtors run twice
1123 
1124  case -1 :
1125  // couldn't fork, error already handled in pstreambuf::fork()
1126  break;
1127 
1128  default :
1129  // this is the parent process
1130  // activate buffers
1131  create_buffers(mode);
1132  ret = this;
1133  }
1134  }
1135  return ret;
1136 #endif
1137  }
1138 
1147  inline void
1149  {
1150  if (fd >= 0 && ::close(fd) == 0)
1151  fd = -1;
1152  }
1153 
1164  template <int N>
1165  inline void
1167  {
1168  for (std::size_t i = 0; i < N; ++i)
1169  close_fd(fds[i]);
1170  }
1171 
1201  template <typename C, typename T>
1203  basic_pstreambuf<C,T>::open( const std::string& file,
1204  const argv_type& argv,
1205  pmode mode )
1206  {
1207  basic_pstreambuf<C,T>* ret = NULL;
1208 
1209  if (!is_open())
1210  {
1211  // constants for read/write ends of pipe
1212  enum { RD, WR };
1213 
1214  // open another pipe and set close-on-exec
1215  fd_type ck_exec[] = { -1, -1 };
1216  if (-1 == ::pipe(ck_exec)
1217  || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC)
1218  || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC))
1219  {
1220  error_ = errno;
1221  close_fd_array(ck_exec);
1222  }
1223  else
1224  {
1225  switch(fork(mode))
1226  {
1227  case 0 :
1228  // this is the new process, exec command
1229  {
1230  char** arg_v = new char*[argv.size()+1];
1231  for (std::size_t i = 0; i < argv.size(); ++i)
1232  {
1233  const std::string& src = argv[i];
1234  char*& dest = arg_v[i];
1235  dest = new char[src.size()+1];
1236  dest[ src.copy(dest, src.size()) ] = '\0';
1237  }
1238  arg_v[argv.size()] = NULL;
1239 
1240  ::execvp(file.c_str(), arg_v);
1241 
1242  // can only reach this point if exec() failed
1243 
1244  // parent can get error code from ck_exec pipe
1245  error_ = errno;
1246 
1247  while (::write(ck_exec[WR], &error_, sizeof(error_)) == -1
1248  && errno == EINTR)
1249  { }
1250 
1251  ::close(ck_exec[WR]);
1252  ::close(ck_exec[RD]);
1253 
1254  ::_exit(error_);
1255  // using std::exit() would make static dtors run twice
1256  }
1257 
1258  case -1 :
1259  // couldn't fork, error already handled in pstreambuf::fork()
1260  close_fd_array(ck_exec);
1261  break;
1262 
1263  default :
1264  // this is the parent process
1265 
1266  // check child called exec() successfully
1267  ::close(ck_exec[WR]);
1268  switch (::read(ck_exec[RD], &error_, sizeof(error_)))
1269  {
1270  case 0:
1271  // activate buffers
1272  create_buffers(mode);
1273  ret = this;
1274  break;
1275  case -1:
1276  error_ = errno;
1277  break;
1278  default:
1279  // error_ contains error code from child
1280  // call wait() to clean up and set ppid_ to 0
1281  this->wait();
1282  break;
1283  }
1284  ::close(ck_exec[RD]);
1285  }
1286  }
1287  }
1288  return ret;
1289  }
1290 
1307  template <typename C, typename T>
1308  pid_t
1310  {
1311  pid_t pid = -1;
1312 
1313  // Three pairs of file descriptors, for pipes connected to the
1314  // process' stdin, stdout and stderr
1315  // (stored in a single array so close_fd_array() can close all at once)
1316  fd_type fd[] = { -1, -1, -1, -1, -1, -1 };
1317  fd_type* const pin = fd;
1318  fd_type* const pout = fd+2;
1319  fd_type* const perr = fd+4;
1320 
1321  // constants for read/write ends of pipe
1322  enum { RD, WR };
1323 
1324  // N.B.
1325  // For the pstreambuf pin is an output stream and
1326  // pout and perr are input streams.
1327 
1328  if (!error_ && mode&pstdin && ::pipe(pin))
1329  error_ = errno;
1330 
1331  if (!error_ && mode&pstdout && ::pipe(pout))
1332  error_ = errno;
1333 
1334  if (!error_ && mode&pstderr && ::pipe(perr))
1335  error_ = errno;
1336 
1337  if (!error_)
1338  {
1339  pid = ::fork();
1340  switch (pid)
1341  {
1342  case 0 :
1343  {
1344  // this is the new process
1345 
1346  // for each open pipe close one end and redirect the
1347  // respective standard stream to the other end
1348 
1349  if (*pin >= 0)
1350  {
1351  ::close(pin[WR]);
1352  ::dup2(pin[RD], STDIN_FILENO);
1353  ::close(pin[RD]);
1354  }
1355  if (*pout >= 0)
1356  {
1357  ::close(pout[RD]);
1358  ::dup2(pout[WR], STDOUT_FILENO);
1359  ::close(pout[WR]);
1360  }
1361  if (*perr >= 0)
1362  {
1363  ::close(perr[RD]);
1364  ::dup2(perr[WR], STDERR_FILENO);
1365  ::close(perr[WR]);
1366  }
1367 
1368 #ifdef _POSIX_JOB_CONTROL
1369  if (mode&newpg)
1370  ::setpgid(0, 0); // Change to a new process group
1371 #endif
1372 
1373  break;
1374  }
1375  case -1 :
1376  {
1377  // couldn't fork for some reason
1378  error_ = errno;
1379  // close any open pipes
1380  close_fd_array(fd);
1381  break;
1382  }
1383  default :
1384  {
1385  // this is the parent process, store process' pid
1386  ppid_ = pid;
1387 
1388  // store one end of open pipes and close other end
1389  if (*pin >= 0)
1390  {
1391  wpipe_ = pin[WR];
1392  ::close(pin[RD]);
1393  }
1394  if (*pout >= 0)
1395  {
1396  rpipe_[rsrc_out] = pout[RD];
1397  ::close(pout[WR]);
1398  }
1399  if (*perr >= 0)
1400  {
1401  rpipe_[rsrc_err] = perr[RD];
1402  ::close(perr[WR]);
1403  }
1404  }
1405  }
1406  }
1407  else
1408  {
1409  // close any pipes we opened before failure
1410  close_fd_array(fd);
1411  }
1412  return pid;
1413  }
1414 
1424  template <typename C, typename T>
1427  {
1428  const bool running = is_open();
1429 
1430  sync(); // this might call wait() and reap the child process
1431 
1432  // rather than trying to work out whether or not we need to clean up
1433  // just do it anyway, all cleanup functions are safe to call twice.
1434 
1435  destroy_buffers(pstdin|pstdout|pstderr);
1436 
1437  // close pipes before wait() so child gets EOF/SIGPIPE
1438  close_fd(wpipe_);
1439  close_fd_array(rpipe_);
1440 
1441  do
1442  {
1443  error_ = 0;
1444  } while (wait() == -1 && error() == EINTR);
1445 
1446  return running ? this : NULL;
1447  }
1448 
1452  template <typename C, typename T>
1453  inline void
1455  {
1456  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1457  rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
1458  rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
1459  }
1460 
1461  template <typename C, typename T>
1462  void
1464  {
1465  if (mode & pstdin)
1466  {
1467  delete[] wbuffer_;
1468  wbuffer_ = new char_type[bufsz];
1469  this->setp(wbuffer_, wbuffer_ + bufsz);
1470  }
1471  if (mode & pstdout)
1472  {
1473  delete[] rbuffer_[rsrc_out];
1474  rbuffer_[rsrc_out] = new char_type[bufsz];
1475  rsrc_ = rsrc_out;
1476  this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
1477  rbuffer_[rsrc_out] + pbsz);
1478  }
1479  if (mode & pstderr)
1480  {
1481  delete[] rbuffer_[rsrc_err];
1482  rbuffer_[rsrc_err] = new char_type[bufsz];
1483  if (!(mode & pstdout))
1484  {
1485  rsrc_ = rsrc_err;
1486  this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
1487  rbuffer_[rsrc_err] + pbsz);
1488  }
1489  }
1490  }
1491 
1492  template <typename C, typename T>
1493  void
1495  {
1496  if (mode & pstdin)
1497  {
1498  this->setp(NULL, NULL);
1499  delete[] wbuffer_;
1500  wbuffer_ = NULL;
1501  }
1502  if (mode & pstdout)
1503  {
1504  if (rsrc_ == rsrc_out)
1505  this->setg(NULL, NULL, NULL);
1506  delete[] rbuffer_[rsrc_out];
1507  rbuffer_[rsrc_out] = NULL;
1508  }
1509  if (mode & pstderr)
1510  {
1511  if (rsrc_ == rsrc_err)
1512  this->setg(NULL, NULL, NULL);
1513  delete[] rbuffer_[rsrc_err];
1514  rbuffer_[rsrc_err] = NULL;
1515  }
1516  }
1517 
1518  template <typename C, typename T>
1521  {
1522  if (rsrc_ != src)
1523  {
1524  char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
1525  this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
1526  for (std::size_t i = 0; i < 3; ++i)
1527  rbufstate_[i] = tmpbufstate[i];
1528  rsrc_ = src;
1529  }
1530  return rsrc_;
1531  }
1532 
1549  template <typename C, typename T>
1550  int
1552  {
1553  int child_exited = -1;
1554  if (is_open())
1555  {
1556  int exit_status;
1557  switch(::waitpid(ppid_, &exit_status, nohang ? WNOHANG : 0))
1558  {
1559  case 0 :
1560  // nohang was true and process has not exited
1561  child_exited = 0;
1562  break;
1563  case -1 :
1564  error_ = errno;
1565  break;
1566  default :
1567  // process has exited
1568  ppid_ = 0;
1569  status_ = exit_status;
1570  child_exited = 1;
1571  // Close wpipe, would get SIGPIPE if we used it.
1572  destroy_buffers(pstdin);
1573  close_fd(wpipe_);
1574  // Must free read buffers and pipes on destruction
1575  // or next call to open()/close()
1576  break;
1577  }
1578  }
1579  return child_exited;
1580  }
1581 
1592  template <typename C, typename T>
1593  inline basic_pstreambuf<C,T>*
1595  {
1596  basic_pstreambuf<C,T>* ret = NULL;
1597  if (is_open())
1598  {
1599  if (::kill(ppid_, signal))
1600  error_ = errno;
1601  else
1602  {
1603 #if 0
1604  // TODO call exited() to check for exit and clean up? leave to user?
1605  if (signal==SIGTERM || signal==SIGKILL)
1606  this->exited();
1607 #endif
1608  ret = this;
1609  }
1610  }
1611  return ret;
1612  }
1613 
1627  template <typename C, typename T>
1628  inline basic_pstreambuf<C,T>*
1630  {
1631  basic_pstreambuf<C,T>* ret = NULL;
1632 #ifdef _POSIX_JOB_CONTROL
1633  if (is_open())
1634  {
1635  pid_t pgid = ::getpgid(ppid_);
1636  if (pgid == -1)
1637  error_ = errno;
1638  else if (pgid == ::getpgrp())
1639  error_ = EPERM; // Don't commit suicide
1640  else if (::killpg(pgid, signal))
1641  error_ = errno;
1642  else
1643  ret = this;
1644  }
1645 #else
1646  error_ = ENOTSUP;
1647 #endif
1648  return ret;
1649  }
1650 
1658  template <typename C, typename T>
1659  inline bool
1661  {
1662  return ppid_ == 0 || wait(true)==1;
1663  }
1664 
1665 
1671  template <typename C, typename T>
1672  inline int
1674  {
1675  return status_;
1676  }
1677 
1681  template <typename C, typename T>
1682  inline int
1684  {
1685  return error_;
1686  }
1687 
1692  template <typename C, typename T>
1693  inline void
1695  {
1696  sync();
1697  destroy_buffers(pstdin);
1698  close_fd(wpipe_);
1699  }
1700 
1711  template <typename C, typename T>
1712  inline bool
1714  {
1715  return ppid_ > 0;
1716  }
1717 
1726  template <typename C, typename T>
1727  inline bool
1729  {
1730  buf_read_src src = readerr ? rsrc_err : rsrc_out;
1731  if (rpipe_[src]>=0)
1732  {
1733  switch_read_buffer(src);
1734  return true;
1735  }
1736  return false;
1737  }
1738 
1749  template <typename C, typename T>
1750  typename basic_pstreambuf<C,T>::int_type
1752  {
1753  if (!empty_buffer())
1754  return traits_type::eof();
1755  else if (!traits_type::eq_int_type(c, traits_type::eof()))
1756  return this->sputc(c);
1757  else
1758  return traits_type::not_eof(c);
1759  }
1760 
1761 
1762  template <typename C, typename T>
1763  int
1765  {
1766  return !exited() && empty_buffer() ? 0 : -1;
1767  }
1768 
1774  template <typename C, typename T>
1775  std::streamsize
1776  basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
1777  {
1778  std::streamsize done = 0;
1779  while (done < n)
1780  {
1781  if (std::streamsize nbuf = this->epptr() - this->pptr())
1782  {
1783  nbuf = std::min(nbuf, n - done);
1784  traits_type::copy(this->pptr(), s + done, nbuf);
1785  this->pbump(nbuf);
1786  done += nbuf;
1787  }
1788  else if (!empty_buffer())
1789  break;
1790  }
1791  return done;
1792  }
1793 
1797  template <typename C, typename T>
1798  bool
1800  {
1801  const std::streamsize count = this->pptr() - this->pbase();
1802  if (count > 0)
1803  {
1804  const std::streamsize written = this->write(this->wbuffer_, count);
1805  if (written > 0)
1806  {
1807  if (const std::streamsize unwritten = count - written)
1808  traits_type::move(this->pbase(), this->pbase()+written, unwritten);
1809  this->pbump(-written);
1810  return true;
1811  }
1812  }
1813  return false;
1814  }
1815 
1823  template <typename C, typename T>
1824  typename basic_pstreambuf<C,T>::int_type
1826  {
1827  if (this->gptr() < this->egptr() || fill_buffer())
1828  return traits_type::to_int_type(*this->gptr());
1829  else
1830  return traits_type::eof();
1831  }
1832 
1841  template <typename C, typename T>
1842  typename basic_pstreambuf<C,T>::int_type
1844  {
1845  if (this->gptr() != this->eback())
1846  {
1847  this->gbump(-1);
1848  if (!traits_type::eq_int_type(c, traits_type::eof()))
1849  *this->gptr() = traits_type::to_char_type(c);
1850  return traits_type::not_eof(c);
1851  }
1852  else
1853  return traits_type::eof();
1854  }
1855 
1856  template <typename C, typename T>
1857  std::streamsize
1859  {
1860  int avail = 0;
1861  if (sizeof(char_type) == 1)
1862  avail = fill_buffer(true) ? this->egptr() - this->gptr() : -1;
1863 #ifdef FIONREAD
1864  else
1865  {
1866  if (::ioctl(rpipe(), FIONREAD, &avail) == -1)
1867  avail = -1;
1868  else if (avail)
1869  avail /= sizeof(char_type);
1870  }
1871 #endif
1872  return std::streamsize(avail);
1873  }
1874 
1878  template <typename C, typename T>
1879  bool
1881  {
1882  const std::streamsize pb1 = this->gptr() - this->eback();
1883  const std::streamsize pb2 = pbsz;
1884  const std::streamsize npb = std::min(pb1, pb2);
1885 
1886  char_type* const rbuf = rbuffer();
1887 
1888  if (npb)
1889  traits_type::move(rbuf + pbsz - npb, this->gptr() - npb, npb);
1890 
1891  std::streamsize rc = -1;
1892 
1893  if (non_blocking)
1894  {
1895  const int flags = ::fcntl(rpipe(), F_GETFL);
1896  if (flags != -1)
1897  {
1898  const bool blocking = !(flags & O_NONBLOCK);
1899  if (blocking)
1900  ::fcntl(rpipe(), F_SETFL, flags | O_NONBLOCK); // set non-blocking
1901 
1902  error_ = 0;
1903  rc = read(rbuf + pbsz, bufsz - pbsz);
1904 
1905  if (rc == -1 && error_ == EAGAIN) // nothing available
1906  rc = 0;
1907  else if (rc == 0) // EOF
1908  rc = -1;
1909 
1910  if (blocking)
1911  ::fcntl(rpipe(), F_SETFL, flags); // restore
1912  }
1913  }
1914  else
1915  rc = read(rbuf + pbsz, bufsz - pbsz);
1916 
1917  if (rc > 0 || (rc == 0 && non_blocking))
1918  {
1919  this->setg( rbuf + pbsz - npb,
1920  rbuf + pbsz,
1921  rbuf + pbsz + rc );
1922  return true;
1923  }
1924  else
1925  {
1926  this->setg(NULL, NULL, NULL);
1927  return false;
1928  }
1929  }
1930 
1938  template <typename C, typename T>
1939  inline std::streamsize
1940  basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n)
1941  {
1942  std::streamsize nwritten = 0;
1943  if (wpipe() >= 0)
1944  {
1945  nwritten = ::write(wpipe(), s, n * sizeof(char_type));
1946  if (nwritten == -1)
1947  error_ = errno;
1948  else
1949  nwritten /= sizeof(char_type);
1950  }
1951  return nwritten;
1952  }
1953 
1961  template <typename C, typename T>
1962  inline std::streamsize
1963  basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
1964  {
1965  std::streamsize nread = 0;
1966  if (rpipe() >= 0)
1967  {
1968  nread = ::read(rpipe(), s, n * sizeof(char_type));
1969  if (nread == -1)
1970  error_ = errno;
1971  else
1972  nread /= sizeof(char_type);
1973  }
1974  return nread;
1975  }
1976 
1978  template <typename C, typename T>
1979  inline pstreams::fd_type&
1981  {
1982  return wpipe_;
1983  }
1984 
1986  template <typename C, typename T>
1987  inline pstreams::fd_type&
1989  {
1990  return rpipe_[rsrc_];
1991  }
1992 
1994  template <typename C, typename T>
1995  inline pstreams::fd_type&
1997  {
1998  return rpipe_[which];
1999  }
2000 
2002  template <typename C, typename T>
2003  inline typename basic_pstreambuf<C,T>::char_type*
2005  {
2006  return rbuffer_[rsrc_];
2007  }
2008 
2009 
2010  /*
2011  * member definitions for pstream_common
2012  */
2013 
2023  template <typename C, typename T>
2024  inline
2026  : std::basic_ios<C,T>(NULL)
2027  , command_()
2028  , buf_()
2029  {
2030  this->std::basic_ios<C,T>::rdbuf(&buf_);
2031  }
2032 
2041  template <typename C, typename T>
2042  inline
2043  pstream_common<C,T>::pstream_common(const std::string& cmd, pmode mode)
2044  : std::basic_ios<C,T>(NULL)
2045  , command_(cmd)
2046  , buf_()
2047  {
2048  this->std::basic_ios<C,T>::rdbuf(&buf_);
2049  do_open(cmd, mode);
2050  }
2051 
2061  template <typename C, typename T>
2062  inline
2063  pstream_common<C,T>::pstream_common( const std::string& file,
2064  const argv_type& argv,
2065  pmode mode )
2066  : std::basic_ios<C,T>(NULL)
2067  , command_(file)
2068  , buf_()
2069  {
2070  this->std::basic_ios<C,T>::rdbuf(&buf_);
2071  do_open(file, argv, mode);
2072  }
2073 
2083  template <typename C, typename T>
2084  inline
2086  {
2087  }
2088 
2097  template <typename C, typename T>
2098  inline void
2099  pstream_common<C,T>::do_open(const std::string& cmd, pmode mode)
2100  {
2101  if (!buf_.open((command_=cmd), mode))
2102  this->setstate(std::ios_base::failbit);
2103  }
2104 
2114  template <typename C, typename T>
2115  inline void
2116  pstream_common<C,T>::do_open( const std::string& file,
2117  const argv_type& argv,
2118  pmode mode )
2119  {
2120  if (!buf_.open((command_=file), argv, mode))
2121  this->setstate(std::ios_base::failbit);
2122  }
2123 
2125  template <typename C, typename T>
2126  inline void
2128  {
2129  if (!buf_.close())
2130  this->setstate(std::ios_base::failbit);
2131  }
2132 
2137  template <typename C, typename T>
2138  inline bool
2140  {
2141  return buf_.is_open();
2142  }
2143 
2145  template <typename C, typename T>
2146  inline const std::string&
2148  {
2149  return command_;
2150  }
2151 
2153  // TODO document behaviour if buffer replaced.
2154  template <typename C, typename T>
2155  inline typename pstream_common<C,T>::streambuf_type*
2157  {
2158  return const_cast<streambuf_type*>(&buf_);
2159  }
2160 
2161 
2162 #if REDI_EVISCERATE_PSTREAMS
2163 
2195  template <typename C, typename T>
2196  std::size_t
2197  basic_pstreambuf<C,T>::fopen(FILE*& in, FILE*& out, FILE*& err)
2198  {
2199  in = out = err = NULL;
2200  std::size_t open_files = 0;
2201  if (wpipe() > -1)
2202  {
2203  if ((in = ::fdopen(wpipe(), "w")))
2204  {
2205  open_files |= pstdin;
2206  }
2207  }
2208  if (rpipe(rsrc_out) > -1)
2209  {
2210  if ((out = ::fdopen(rpipe(rsrc_out), "r")))
2211  {
2212  open_files |= pstdout;
2213  }
2214  }
2215  if (rpipe(rsrc_err) > -1)
2216  {
2217  if ((err = ::fdopen(rpipe(rsrc_err), "r")))
2218  {
2219  open_files |= pstderr;
2220  }
2221  }
2222  return open_files;
2223  }
2224 
2235  template <typename C, typename T>
2236  inline std::size_t
2237  pstream_common<C,T>::fopen(FILE*& fin, FILE*& fout, FILE*& ferr)
2238  {
2239  return buf_.fopen(fin, fout, ferr);
2240  }
2241 
2242 #endif // REDI_EVISCERATE_PSTREAMS
2243 
2244 
2245 } // namespace redi
2246 
2252 #endif // REDI_PSTREAM_H_SEEN
2253 
2254 // vim: ts=2 sw=2 expandtab
2255 
void close_fd(pstreams::fd_type &fd)
Helper function to close a file descriptor.
Definition: pstream.h:1148
int_type overflow(int_type c)
Transfer characters to the pipe when character buffer overflows.
Definition: pstream.h:1751
std::streamsize write(const char_type *s, std::streamsize n)
Insert a sequence of characters into the pipe.
Definition: pstream.h:1940
int error() const
Return the error number (errno) for the most recent failed operation.
Definition: pstream.h:1683
void open(const std::string &cmd, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:906
basic_opstream(const std::string &cmd, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:529
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:823
fd_type fd_t
Definition: pstream.h:101
~basic_pstream()
Destructor.
Definition: pstream.h:725
fd_type & wpipe()
Return the file descriptor for the output pipe.
Definition: pstream.h:1980
Class template for Bidirectional PStreams.
Definition: pstream.h:636
char_type * rbuffer()
Return the active input buffer.
Definition: pstream.h:2004
Class template for stream buffer.
Definition: pstream.h:89
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:356
std::streamsize read(char_type *s, std::streamsize n)
Extract a sequence of characters from the pipe.
Definition: pstream.h:1963
basic_rpstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:826
basic_pstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:654
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:508
bool read_err(bool readerr=true)
Change active input source.
Definition: pstream.h:1728
virtual ~pstream_common()=0
Pure virtual destructor.
Definition: pstream.h:2085
void close_fd_array(pstreams::fd_type(&fds)[N])
Helper function to close an array of file descriptors.
Definition: pstream.h:1166
std::vector< std::string > argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:70
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:359
pstream_common()
Default constructor.
Definition: pstream.h:2025
int_type underflow()
Transfer characters from the pipe when the character buffer is empty.
Definition: pstream.h:1825
void open(const std::string &cmd, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:737
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:922
Class template for common base class.
Definition: pstream.h:265
basic_rpstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:873
basic_ipstream(const argv_type &argv, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:409
basic_pstream(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:684
basic_opstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:514
basic_pstreambuf< char > pstreambuf
Type definition for common template specialisation.
Definition: pstream.h:956
basic_ipstream(const std::string &cmd, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:377
static const pmode pstderr
Read from stderr.
Definition: pstream.h:77
streambuf_type * rdbuf() const
Return a pointer to the stream buffer.
Definition: pstream.h:2156
int_type pbackfail(int_type c=traits_type::eof())
Make a character available to be returned by the next extraction.
Definition: pstream.h:1843
Common base class providing constants and typenames.
Definition: pstream.h:64
void open(const std::string &cmd, pmode mode=pstdout)
Start a process.
Definition: pstream.h:439
bool fill_buffer(bool non_blocking=false)
Definition: pstream.h:1880
static const pmode pstdout
Read from stdout.
Definition: pstream.h:76
int sync()
Write any buffered characters to the stream.
Definition: pstream.h:1764
basic_rpstream(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:856
basic_pstreambuf()
Default constructor.
Definition: pstream.h:1003
std::string command_
The command used to start the process.
Definition: pstream.h:320
bool exited()
Report whether the process has exited.
Definition: pstream.h:1660
streambuf_type buf_
The stream buffer.
Definition: pstream.h:321
buf_read_src
Enumerated type to indicate whether stdout or stderr is to be read.
Definition: pstream.h:202
basic_pstream & out()
Set streambuf to read from process&#39; stdout.
Definition: pstream.h:765
bool is_open() const
Report whether the stream&#39;s buffer has been initialised.
Definition: pstream.h:2139
basic_pstream(const std::string &cmd, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:669
basic_pstreambuf * open(const std::string &cmd, pmode mode)
Initialise the stream buffer with cmd.
Definition: pstream.h:1101
basic_ipstream(const std::string &file, const argv_type &argv, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:392
Class template for Input PStreams.
Definition: pstream.h:336
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:651
std::streamsize xsputn(const char_type *s, std::streamsize n)
Insert multiple characters into the pipe.
Definition: pstream.h:1776
pid_t fork(pmode mode)
Initialise pipes and fork process.
Definition: pstream.h:1309
basic_ipstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:478
basic_pstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:776
basic_opstream(const argv_type &argv, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:561
basic_rpstream< char > rpstream
Type definition for common template specialisation.
Definition: pstream.h:964
basic_ipstream & out()
Set streambuf to read from process&#39; stdout.
Definition: pstream.h:467
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:511
All PStreams classes are declared in namespace redi.
int fd_type
Type used for file descriptors.
Definition: pstream.h:73
~basic_pstreambuf()
Destructor.
Definition: pstream.h:1067
basic_pstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:701
std::ios_base::openmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:67
Class template for Restricted PStreams.
Definition: pstream.h:806
basic_pstreambuf * killpg(int signal=SIGTERM)
Send a signal to the process&#39; process group.
Definition: pstream.h:1629
basic_pstreambuf * close()
Close the stream buffer and wait for the process to exit.
Definition: pstream.h:1426
bool is_open() const
Report whether the stream buffer has been initialised.
Definition: pstream.h:1713
bool empty_buffer()
Writes buffered characters to the process&#39; stdin pipe.
Definition: pstream.h:1799
void open(const std::string &cmd, pmode mode=pstdin)
Start a process.
Definition: pstream.h:597
~basic_ipstream()
Destructor.
Definition: pstream.h:426
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:820
std::basic_ostream< C, T > & peof(std::basic_ostream< C, T > &s)
Manipulator to close the pipe connected to the process&#39; stdin.
Definition: pstream.h:981
basic_ipstream< char > ipstream
Type definition for common template specialisation.
Definition: pstream.h:958
int wait(bool nohang=false)
Wait for the child process to exit.
Definition: pstream.h:1551
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout)
Start a process.
Definition: pstream.h:455
Class template for Output PStreams.
Definition: pstream.h:496
const std::string & command() const
Return the command used to initialise the stream.
Definition: pstream.h:2147
static const pmode newpg
Create a new process group for the child process.
Definition: pstream.h:80
fd_type & rpipe()
Return the file descriptor for the active input pipe.
Definition: pstream.h:1988
void do_open(const std::string &cmd, pmode mode)
Start a process.
Definition: pstream.h:2099
istream_type & err()
Obtain a reference to the istream that reads the process&#39; stderr.
Definition: pstream.h:947
basic_ipstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:362
~basic_rpstream()
Destructor.
Definition: pstream.h:894
void close()
Close the pipe.
Definition: pstream.h:2127
void peof()
Close the pipe connected to the process&#39; stdin.
Definition: pstream.h:1694
basic_opstream< char > opstream
Type definition for common template specialisation.
Definition: pstream.h:960
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:648
void open(const std::string &file, const argv_type &argv, pmode mode=pstdin)
Start a process.
Definition: pstream.h:613
int status() const
Return the exit status of the process.
Definition: pstream.h:1673
basic_pstream< char > pstream
Type definition for common template specialisation.
Definition: pstream.h:962
static const pmode pstdin
Write to stdin.
Definition: pstream.h:75
std::streamsize showmanyc()
Report how many characters can be read from active input without blocking.
Definition: pstream.h:1858
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:753
basic_rpstream(const std::string &cmd, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:841
basic_opstream(const std::string &file, const argv_type &argv, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:544
basic_pstreambuf * kill(int signal=SIGTERM)
Send a signal to the process.
Definition: pstream.h:1594
istream_type & out()
Obtain a reference to the istream that reads the process&#39; stdout.
Definition: pstream.h:935
~basic_opstream()
Destructor.
Definition: pstream.h:585