PStreams
pstream.h
Go to the documentation of this file.
1 /*
2 PStreams - POSIX Process I/O for C++
3 Copyright (C) 2001-2014 Jonathan Wakely
4 
5 This file is part of PStreams.
6 
7 PStreams is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 
12 PStreams is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
30 #ifndef REDI_PSTREAM_H_SEEN
31 #define REDI_PSTREAM_H_SEEN
32 
33 #include <ios>
34 #include <streambuf>
35 #include <istream>
36 #include <ostream>
37 #include <string>
38 #include <vector>
39 #include <algorithm> // for min()
40 #include <cerrno> // for errno
41 #include <cstddef> // for size_t, NULL
42 #include <cstdlib> // for exit()
43 #include <sys/types.h> // for pid_t
44 #include <sys/wait.h> // for waitpid()
45 #include <sys/ioctl.h> // for ioctl() and FIONREAD
46 #if defined(__sun)
47 # include <sys/filio.h> // for FIONREAD on Solaris 2.5
48 #endif
49 #include <unistd.h> // for pipe() fork() exec() and filedes functions
50 #include <signal.h> // for kill()
51 #include <fcntl.h> // for fcntl()
52 #if REDI_EVISCERATE_PSTREAMS
53 # include <stdio.h> // for FILE, fdopen()
54 #endif
55 
56 
58 #define PSTREAMS_VERSION 0x0081 // 0.8.1
59 
73 namespace redi
74 {
76  struct pstreams
77  {
79  typedef std::ios_base::openmode pmode;
80 
82  typedef std::vector<std::string> argv_type;
83 
85  typedef int fd_type;
86 
87  static const pmode pstdin = std::ios_base::out;
88  static const pmode pstdout = std::ios_base::in;
89  static const pmode pstderr = std::ios_base::app;
90 
92  static const pmode newpg = std::ios_base::trunc;
93 
94  protected:
95  enum { bufsz = 32 };
96  enum { pbsz = 2 };
97  };
98 
100  template <typename CharT, typename Traits = std::char_traits<CharT> >
102  : public std::basic_streambuf<CharT, Traits>
103  , public pstreams
104  {
105  public:
106  // Type definitions for dependent types
107  typedef CharT char_type;
108  typedef Traits traits_type;
109  typedef typename traits_type::int_type int_type;
110  typedef typename traits_type::off_type off_type;
111  typedef typename traits_type::pos_type pos_type;
113  typedef fd_type fd_t;
114 
117 
119  basic_pstreambuf(const std::string& command, pmode mode);
120 
122  basic_pstreambuf( const std::string& file,
123  const argv_type& argv,
124  pmode mode );
125 
127  ~basic_pstreambuf();
128 
131  open(const std::string& command, pmode mode);
132 
135  open(const std::string& file, const argv_type& argv, pmode mode);
136 
139  close();
140 
143  kill(int signal = SIGTERM);
144 
147  killpg(int signal = SIGTERM);
148 
150  void
151  peof();
152 
154  bool
155  read_err(bool readerr = true);
156 
158  bool
159  is_open() const;
160 
162  bool
163  exited();
164 
165 #if REDI_EVISCERATE_PSTREAMS
166  std::size_t
168  fopen(FILE*& in, FILE*& out, FILE*& err);
169 #endif
170 
172  int
173  status() const;
174 
176  int
177  error() const;
178 
179  protected:
181  int_type
182  overflow(int_type c);
183 
185  int_type
186  underflow();
187 
189  int_type
190  pbackfail(int_type c = traits_type::eof());
191 
193  int
194  sync();
195 
197  std::streamsize
198  xsputn(const char_type* s, std::streamsize n);
199 
201  std::streamsize
202  write(const char_type* s, std::streamsize n);
203 
205  std::streamsize
206  read(char_type* s, std::streamsize n);
207 
209  std::streamsize
210  showmanyc();
211 
212  protected:
214  enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
215 
217  pid_t
218  fork(pmode mode);
219 
221  int
222  wait(bool nohang = false);
223 
225  fd_type&
226  wpipe();
227 
229  fd_type&
230  rpipe();
231 
233  fd_type&
234  rpipe(buf_read_src which);
235 
236  void
237  create_buffers(pmode mode);
238 
239  void
240  destroy_buffers(pmode mode);
241 
243  bool
244  empty_buffer();
245 
246  bool
247  fill_buffer(bool non_blocking = false);
248 
250  char_type*
251  rbuffer();
252 
254  switch_read_buffer(buf_read_src);
255 
256  private:
258  basic_pstreambuf& operator=(const basic_pstreambuf&);
259 
260  void
261  init_rbuffers();
262 
263  pid_t ppid_; // pid of process
264  fd_type wpipe_; // pipe used to write to process' stdin
265  fd_type rpipe_[2]; // two pipes to read from, stdout and stderr
266  char_type* wbuffer_;
267  char_type* rbuffer_[2];
268  char_type* rbufstate_[3];
270  buf_read_src rsrc_;
271  int status_; // hold exit status of child process
272  int error_; // hold errno if fork() or exec() fails
273  };
274 
276  template <typename CharT, typename Traits = std::char_traits<CharT> >
278  : virtual public std::basic_ios<CharT, Traits>
279  , virtual public pstreams
280  {
281  protected:
283 
284  typedef pstreams::pmode pmode;
286 
288  pstream_common();
289 
291  pstream_common(const std::string& command, pmode mode);
292 
294  pstream_common(const std::string& file, const argv_type& argv, pmode mode);
295 
297  virtual
298  ~pstream_common() = 0;
299 
301  void
302  do_open(const std::string& command, pmode mode);
303 
305  void
306  do_open(const std::string& file, const argv_type& argv, pmode mode);
307 
308  public:
310  void
311  close();
312 
314  bool
315  is_open() const;
316 
318  const std::string&
319  command() const;
320 
322  streambuf_type*
323  rdbuf() const;
324 
325 #if REDI_EVISCERATE_PSTREAMS
326  std::size_t
328  fopen(FILE*& in, FILE*& out, FILE*& err);
329 #endif
330 
331  protected:
332  std::string command_;
333  streambuf_type buf_;
334  };
335 
336 
347  template <typename CharT, typename Traits = std::char_traits<CharT> >
349  : public std::basic_istream<CharT, Traits>
350  , public pstream_common<CharT, Traits>
351  , virtual public pstreams
352  {
353  typedef std::basic_istream<CharT, Traits> istream_type;
355 
356  using pbase_type::buf_; // declare name in this scope
357 
358  // Ensure a basic_ipstream will read from at least one pipe
359  pmode readable(pmode mode)
360  {
361  if (!(mode & (pstdout|pstderr)))
362  mode |= pstdout;
363  return mode;
364  }
365 
366  public:
368  typedef typename pbase_type::pmode pmode;
369 
371  typedef typename pbase_type::argv_type argv_type;
372 
375  : istream_type(NULL), pbase_type()
376  { }
377 
388  explicit
389  basic_ipstream(const std::string& command, pmode mode = pstdout)
390  : istream_type(NULL), pbase_type(command, readable(mode))
391  { }
392 
404  basic_ipstream( const std::string& file,
405  const argv_type& argv,
406  pmode mode = pstdout )
407  : istream_type(NULL), pbase_type(file, argv, readable(mode))
408  { }
409 
420  explicit
421  basic_ipstream(const argv_type& argv, pmode mode = pstdout)
422  : istream_type(NULL), pbase_type(argv.at(0), argv, readable(mode))
423  { }
424 
425 #if __cplusplus >= 201103L
426  template<typename T>
427  explicit
428  basic_ipstream(std::initializer_list<T> args, pmode mode = pstdout)
429  : basic_ipstream(argv_type(args.begin(), args.end()), mode)
430  { }
431 #endif
432 
439  { }
440 
450  void
451  open(const std::string& command, pmode mode = pstdout)
452  {
453  this->do_open(command, readable(mode));
454  }
455 
466  void
467  open( const std::string& file,
468  const argv_type& argv,
469  pmode mode = pstdout )
470  {
471  this->do_open(file, argv, readable(mode));
472  }
473 
479  out()
480  {
481  this->buf_.read_err(false);
482  return *this;
483  }
484 
490  err()
491  {
492  this->buf_.read_err(true);
493  return *this;
494  }
495  };
496 
497 
507  template <typename CharT, typename Traits = std::char_traits<CharT> >
509  : public std::basic_ostream<CharT, Traits>
510  , public pstream_common<CharT, Traits>
511  , virtual public pstreams
512  {
513  typedef std::basic_ostream<CharT, Traits> ostream_type;
515 
516  using pbase_type::buf_; // declare name in this scope
517 
518  public:
520  typedef typename pbase_type::pmode pmode;
521 
523  typedef typename pbase_type::argv_type argv_type;
524 
527  : ostream_type(NULL), pbase_type()
528  { }
529 
540  explicit
541  basic_opstream(const std::string& command, pmode mode = pstdin)
542  : ostream_type(NULL), pbase_type(command, mode|pstdin)
543  { }
544 
556  basic_opstream( const std::string& file,
557  const argv_type& argv,
558  pmode mode = pstdin )
559  : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
560  { }
561 
572  explicit
573  basic_opstream(const argv_type& argv, pmode mode = pstdin)
574  : ostream_type(NULL), pbase_type(argv.at(0), argv, mode|pstdin)
575  { }
576 
577 #if __cplusplus >= 201103L
578 
585  template<typename T>
586  explicit
587  basic_opstream(std::initializer_list<T> args, pmode mode = pstdin)
588  : basic_opstream(argv_type(args.begin(), args.end()), mode)
589  { }
590 #endif
591 
598 
608  void
609  open(const std::string& command, pmode mode = pstdin)
610  {
611  this->do_open(command, mode|pstdin);
612  }
613 
624  void
625  open( const std::string& file,
626  const argv_type& argv,
627  pmode mode = pstdin)
628  {
629  this->do_open(file, argv, mode|pstdin);
630  }
631  };
632 
633 
647  template <typename CharT, typename Traits = std::char_traits<CharT> >
649  : public std::basic_iostream<CharT, Traits>
650  , public pstream_common<CharT, Traits>
651  , virtual public pstreams
652  {
653  typedef std::basic_iostream<CharT, Traits> iostream_type;
655 
656  using pbase_type::buf_; // declare name in this scope
657 
658  public:
660  typedef typename pbase_type::pmode pmode;
661 
663  typedef typename pbase_type::argv_type argv_type;
664 
667  : iostream_type(NULL), pbase_type()
668  { }
669 
680  explicit
681  basic_pstream(const std::string& command, pmode mode = pstdout|pstdin)
682  : iostream_type(NULL), pbase_type(command, mode)
683  { }
684 
696  basic_pstream( const std::string& file,
697  const argv_type& argv,
698  pmode mode = pstdout|pstdin )
699  : iostream_type(NULL), pbase_type(file, argv, mode)
700  { }
701 
712  explicit
713  basic_pstream(const argv_type& argv, pmode mode = pstdout|pstdin)
714  : iostream_type(NULL), pbase_type(argv.at(0), argv, mode)
715  { }
716 
717 #if __cplusplus >= 201103L
718 
725  template<typename T>
726  explicit
727  basic_pstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
728  : basic_pstream(argv_type(l.begin(), l.end()), mode)
729  { }
730 #endif
731 
738 
748  void
749  open(const std::string& command, pmode mode = pstdout|pstdin)
750  {
751  this->do_open(command, mode);
752  }
753 
764  void
765  open( const std::string& file,
766  const argv_type& argv,
767  pmode mode = pstdout|pstdin )
768  {
769  this->do_open(file, argv, mode);
770  }
771 
777  out()
778  {
779  this->buf_.read_err(false);
780  return *this;
781  }
782 
788  err()
789  {
790  this->buf_.read_err(true);
791  return *this;
792  }
793  };
794 
795 
817  template <typename CharT, typename Traits = std::char_traits<CharT> >
819  : public std::basic_ostream<CharT, Traits>
820  , private std::basic_istream<CharT, Traits>
821  , private pstream_common<CharT, Traits>
822  , virtual public pstreams
823  {
824  typedef std::basic_ostream<CharT, Traits> ostream_type;
825  typedef std::basic_istream<CharT, Traits> istream_type;
827 
828  using pbase_type::buf_; // declare name in this scope
829 
830  public:
832  typedef typename pbase_type::pmode pmode;
833 
835  typedef typename pbase_type::argv_type argv_type;
836 
839  : ostream_type(NULL), istream_type(NULL), pbase_type()
840  { }
841 
852  explicit
853  basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin)
854  : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode)
855  { }
856 
868  basic_rpstream( const std::string& file,
869  const argv_type& argv,
870  pmode mode = pstdout|pstdin )
871  : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
872  { }
873 
884  explicit
885  basic_rpstream(const argv_type& argv, pmode mode = pstdout|pstdin)
886  : ostream_type(NULL), istream_type(NULL),
887  pbase_type(argv.at(0), argv, mode)
888  { }
889 
890 #if __cplusplus >= 201103L
891 
898  template<typename T>
899  explicit
900  basic_rpstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
901  : basic_rpstream(argv_type(l.begin(), l.end()), mode)
902  { }
903 #endif
904 
907 
917  void
918  open(const std::string& command, pmode mode = pstdout|pstdin)
919  {
920  this->do_open(command, mode);
921  }
922 
933  void
934  open( const std::string& file,
935  const argv_type& argv,
936  pmode mode = pstdout|pstdin )
937  {
938  this->do_open(file, argv, mode);
939  }
940 
946  istream_type&
947  out()
948  {
949  this->buf_.read_err(false);
950  return *this;
951  }
952 
958  istream_type&
959  err()
960  {
961  this->buf_.read_err(true);
962  return *this;
963  }
964  };
965 
966 
977 
978 
991  template <typename C, typename T>
992  inline std::basic_ostream<C,T>&
993  peof(std::basic_ostream<C,T>& s)
994  {
996  if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf()))
997  p->peof();
998  return s;
999  }
1000 
1001 
1002  /*
1003  * member definitions for pstreambuf
1004  */
1005 
1006 
1013  template <typename C, typename T>
1014  inline
1016  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1017  , wpipe_(-1)
1018  , wbuffer_(NULL)
1019  , rsrc_(rsrc_out)
1020  , status_(-1)
1021  , error_(0)
1022  {
1023  init_rbuffers();
1024  }
1025 
1034  template <typename C, typename T>
1035  inline
1036  basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode)
1037  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1038  , wpipe_(-1)
1039  , wbuffer_(NULL)
1040  , rsrc_(rsrc_out)
1041  , status_(-1)
1042  , error_(0)
1043  {
1044  init_rbuffers();
1045  open(command, mode);
1046  }
1047 
1057  template <typename C, typename T>
1058  inline
1060  const argv_type& argv,
1061  pmode mode )
1062  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1063  , wpipe_(-1)
1064  , wbuffer_(NULL)
1065  , rsrc_(rsrc_out)
1066  , status_(-1)
1067  , error_(0)
1068  {
1069  init_rbuffers();
1070  open(file, argv, mode);
1071  }
1072 
1077  template <typename C, typename T>
1078  inline
1080  {
1081  close();
1082  }
1083 
1111  template <typename C, typename T>
1113  basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
1114  {
1115  const char * shell_path = "/bin/sh";
1116 #if 0
1117  const std::string argv[] = { "sh", "-c", command };
1118  return this->open(shell_path, argv_type(argv, argv+3), mode);
1119 #else
1120  basic_pstreambuf<C,T>* ret = NULL;
1121 
1122  if (!is_open())
1123  {
1124  switch(fork(mode))
1125  {
1126  case 0 :
1127  // this is the new process, exec command
1128  ::execl(shell_path, "sh", "-c", command.c_str(), (char*)NULL);
1129 
1130  // can only reach this point if exec() failed
1131 
1132  // parent can get exit code from waitpid()
1133  ::_exit(errno);
1134  // using std::exit() would make static dtors run twice
1135 
1136  case -1 :
1137  // couldn't fork, error already handled in pstreambuf::fork()
1138  break;
1139 
1140  default :
1141  // this is the parent process
1142  // activate buffers
1143  create_buffers(mode);
1144  ret = this;
1145  }
1146  }
1147  return ret;
1148 #endif
1149  }
1150 
1159  inline void
1161  {
1162  if (fd >= 0 && ::close(fd) == 0)
1163  fd = -1;
1164  }
1165 
1176  template <int N>
1177  inline void
1179  {
1180  for (std::size_t i = 0; i < N; ++i)
1181  close_fd(fds[i]);
1182  }
1183 
1213  template <typename C, typename T>
1215  basic_pstreambuf<C,T>::open( const std::string& file,
1216  const argv_type& argv,
1217  pmode mode )
1218  {
1219  basic_pstreambuf<C,T>* ret = NULL;
1220 
1221  if (!is_open())
1222  {
1223  // constants for read/write ends of pipe
1224  enum { RD, WR };
1225 
1226  // open another pipe and set close-on-exec
1227  fd_type ck_exec[] = { -1, -1 };
1228  if (-1 == ::pipe(ck_exec)
1229  || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC)
1230  || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC))
1231  {
1232  error_ = errno;
1233  close_fd_array(ck_exec);
1234  }
1235  else
1236  {
1237  switch(fork(mode))
1238  {
1239  case 0 :
1240  // this is the new process, exec command
1241  {
1242  char** arg_v = new char*[argv.size()+1];
1243  for (std::size_t i = 0; i < argv.size(); ++i)
1244  {
1245  const std::string& src = argv[i];
1246  char*& dest = arg_v[i];
1247  dest = new char[src.size()+1];
1248  dest[ src.copy(dest, src.size()) ] = '\0';
1249  }
1250  arg_v[argv.size()] = NULL;
1251 
1252  ::execvp(file.c_str(), arg_v);
1253 
1254  // can only reach this point if exec() failed
1255 
1256  // parent can get error code from ck_exec pipe
1257  error_ = errno;
1258 
1259  while (::write(ck_exec[WR], &error_, sizeof(error_)) == -1
1260  && errno == EINTR)
1261  { }
1262 
1263  ::close(ck_exec[WR]);
1264  ::close(ck_exec[RD]);
1265 
1266  ::_exit(error_);
1267  // using std::exit() would make static dtors run twice
1268  }
1269 
1270  case -1 :
1271  // couldn't fork, error already handled in pstreambuf::fork()
1272  close_fd_array(ck_exec);
1273  break;
1274 
1275  default :
1276  // this is the parent process
1277 
1278  // check child called exec() successfully
1279  ::close(ck_exec[WR]);
1280  switch (::read(ck_exec[RD], &error_, sizeof(error_)))
1281  {
1282  case 0:
1283  // activate buffers
1284  create_buffers(mode);
1285  ret = this;
1286  break;
1287  case -1:
1288  error_ = errno;
1289  break;
1290  default:
1291  // error_ contains error code from child
1292  // call wait() to clean up and set ppid_ to 0
1293  this->wait();
1294  break;
1295  }
1296  ::close(ck_exec[RD]);
1297  }
1298  }
1299  }
1300  return ret;
1301  }
1302 
1319  template <typename C, typename T>
1320  pid_t
1322  {
1323  pid_t pid = -1;
1324 
1325  // Three pairs of file descriptors, for pipes connected to the
1326  // process' stdin, stdout and stderr
1327  // (stored in a single array so close_fd_array() can close all at once)
1328  fd_type fd[] = { -1, -1, -1, -1, -1, -1 };
1329  fd_type* const pin = fd;
1330  fd_type* const pout = fd+2;
1331  fd_type* const perr = fd+4;
1332 
1333  // constants for read/write ends of pipe
1334  enum { RD, WR };
1335 
1336  // N.B.
1337  // For the pstreambuf pin is an output stream and
1338  // pout and perr are input streams.
1339 
1340  if (!error_ && mode&pstdin && ::pipe(pin))
1341  error_ = errno;
1342 
1343  if (!error_ && mode&pstdout && ::pipe(pout))
1344  error_ = errno;
1345 
1346  if (!error_ && mode&pstderr && ::pipe(perr))
1347  error_ = errno;
1348 
1349  if (!error_)
1350  {
1351  pid = ::fork();
1352  switch (pid)
1353  {
1354  case 0 :
1355  {
1356  // this is the new process
1357 
1358  // for each open pipe close one end and redirect the
1359  // respective standard stream to the other end
1360 
1361  if (*pin >= 0)
1362  {
1363  ::close(pin[WR]);
1364  ::dup2(pin[RD], STDIN_FILENO);
1365  ::close(pin[RD]);
1366  }
1367  if (*pout >= 0)
1368  {
1369  ::close(pout[RD]);
1370  ::dup2(pout[WR], STDOUT_FILENO);
1371  ::close(pout[WR]);
1372  }
1373  if (*perr >= 0)
1374  {
1375  ::close(perr[RD]);
1376  ::dup2(perr[WR], STDERR_FILENO);
1377  ::close(perr[WR]);
1378  }
1379 
1380 #ifdef _POSIX_JOB_CONTROL
1381  if (mode&newpg)
1382  ::setpgid(0, 0); // Change to a new process group
1383 #endif
1384 
1385  break;
1386  }
1387  case -1 :
1388  {
1389  // couldn't fork for some reason
1390  error_ = errno;
1391  // close any open pipes
1392  close_fd_array(fd);
1393  break;
1394  }
1395  default :
1396  {
1397  // this is the parent process, store process' pid
1398  ppid_ = pid;
1399 
1400  // store one end of open pipes and close other end
1401  if (*pin >= 0)
1402  {
1403  wpipe_ = pin[WR];
1404  ::close(pin[RD]);
1405  }
1406  if (*pout >= 0)
1407  {
1408  rpipe_[rsrc_out] = pout[RD];
1409  ::close(pout[WR]);
1410  }
1411  if (*perr >= 0)
1412  {
1413  rpipe_[rsrc_err] = perr[RD];
1414  ::close(perr[WR]);
1415  }
1416  }
1417  }
1418  }
1419  else
1420  {
1421  // close any pipes we opened before failure
1422  close_fd_array(fd);
1423  }
1424  return pid;
1425  }
1426 
1436  template <typename C, typename T>
1439  {
1440  const bool running = is_open();
1441 
1442  sync(); // this might call wait() and reap the child process
1443 
1444  // rather than trying to work out whether or not we need to clean up
1445  // just do it anyway, all cleanup functions are safe to call twice.
1446 
1447  destroy_buffers(pstdin|pstdout|pstderr);
1448 
1449  // close pipes before wait() so child gets EOF/SIGPIPE
1450  close_fd(wpipe_);
1451  close_fd_array(rpipe_);
1452 
1453  do
1454  {
1455  error_ = 0;
1456  } while (wait() == -1 && error() == EINTR);
1457 
1458  return running ? this : NULL;
1459  }
1460 
1464  template <typename C, typename T>
1465  inline void
1467  {
1468  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1469  rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
1470  rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
1471  }
1472 
1473  template <typename C, typename T>
1474  void
1476  {
1477  if (mode & pstdin)
1478  {
1479  delete[] wbuffer_;
1480  wbuffer_ = new char_type[bufsz];
1481  this->setp(wbuffer_, wbuffer_ + bufsz);
1482  }
1483  if (mode & pstdout)
1484  {
1485  delete[] rbuffer_[rsrc_out];
1486  rbuffer_[rsrc_out] = new char_type[bufsz];
1487  rsrc_ = rsrc_out;
1488  this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
1489  rbuffer_[rsrc_out] + pbsz);
1490  }
1491  if (mode & pstderr)
1492  {
1493  delete[] rbuffer_[rsrc_err];
1494  rbuffer_[rsrc_err] = new char_type[bufsz];
1495  if (!(mode & pstdout))
1496  {
1497  rsrc_ = rsrc_err;
1498  this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
1499  rbuffer_[rsrc_err] + pbsz);
1500  }
1501  }
1502  }
1503 
1504  template <typename C, typename T>
1505  void
1507  {
1508  if (mode & pstdin)
1509  {
1510  this->setp(NULL, NULL);
1511  delete[] wbuffer_;
1512  wbuffer_ = NULL;
1513  }
1514  if (mode & pstdout)
1515  {
1516  if (rsrc_ == rsrc_out)
1517  this->setg(NULL, NULL, NULL);
1518  delete[] rbuffer_[rsrc_out];
1519  rbuffer_[rsrc_out] = NULL;
1520  }
1521  if (mode & pstderr)
1522  {
1523  if (rsrc_ == rsrc_err)
1524  this->setg(NULL, NULL, NULL);
1525  delete[] rbuffer_[rsrc_err];
1526  rbuffer_[rsrc_err] = NULL;
1527  }
1528  }
1529 
1530  template <typename C, typename T>
1533  {
1534  if (rsrc_ != src)
1535  {
1536  char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
1537  this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
1538  for (std::size_t i = 0; i < 3; ++i)
1539  rbufstate_[i] = tmpbufstate[i];
1540  rsrc_ = src;
1541  }
1542  return rsrc_;
1543  }
1544 
1561  template <typename C, typename T>
1562  int
1564  {
1565  int exited = -1;
1566  if (is_open())
1567  {
1568  int status;
1569  switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0))
1570  {
1571  case 0 :
1572  // nohang was true and process has not exited
1573  exited = 0;
1574  break;
1575  case -1 :
1576  error_ = errno;
1577  break;
1578  default :
1579  // process has exited
1580  ppid_ = 0;
1581  status_ = status;
1582  exited = 1;
1583  // Close wpipe, would get SIGPIPE if we used it.
1584  destroy_buffers(pstdin);
1585  close_fd(wpipe_);
1586  // Must free read buffers and pipes on destruction
1587  // or next call to open()/close()
1588  break;
1589  }
1590  }
1591  return exited;
1592  }
1593 
1604  template <typename C, typename T>
1605  inline basic_pstreambuf<C,T>*
1607  {
1608  basic_pstreambuf<C,T>* ret = NULL;
1609  if (is_open())
1610  {
1611  if (::kill(ppid_, signal))
1612  error_ = errno;
1613  else
1614  {
1615 #if 0
1616  // TODO call exited() to check for exit and clean up? leave to user?
1617  if (signal==SIGTERM || signal==SIGKILL)
1618  this->exited();
1619 #endif
1620  ret = this;
1621  }
1622  }
1623  return ret;
1624  }
1625 
1639  template <typename C, typename T>
1640  inline basic_pstreambuf<C,T>*
1642  {
1643  basic_pstreambuf<C,T>* ret = NULL;
1644 #ifdef _POSIX_JOB_CONTROL
1645  if (is_open())
1646  {
1647  pid_t pgid = ::getpgid(ppid_);
1648  if (pgid == -1)
1649  error_ = errno;
1650  else if (pgid == ::getpgrp())
1651  error_ = EPERM; // Don't commit suicide
1652  else if (::killpg(pgid, signal))
1653  error_ = errno;
1654  else
1655  ret = this;
1656  }
1657 #else
1658  error_ = ENOTSUP;
1659 #endif
1660  return ret;
1661  }
1662 
1670  template <typename C, typename T>
1671  inline bool
1673  {
1674  return ppid_ == 0 || wait(true)==1;
1675  }
1676 
1677 
1683  template <typename C, typename T>
1684  inline int
1686  {
1687  return status_;
1688  }
1689 
1693  template <typename C, typename T>
1694  inline int
1696  {
1697  return error_;
1698  }
1699 
1704  template <typename C, typename T>
1705  inline void
1707  {
1708  sync();
1709  destroy_buffers(pstdin);
1710  close_fd(wpipe_);
1711  }
1712 
1723  template <typename C, typename T>
1724  inline bool
1726  {
1727  return ppid_ > 0;
1728  }
1729 
1738  template <typename C, typename T>
1739  inline bool
1741  {
1742  buf_read_src src = readerr ? rsrc_err : rsrc_out;
1743  if (rpipe_[src]>=0)
1744  {
1745  switch_read_buffer(src);
1746  return true;
1747  }
1748  return false;
1749  }
1750 
1761  template <typename C, typename T>
1762  typename basic_pstreambuf<C,T>::int_type
1764  {
1765  if (!empty_buffer())
1766  return traits_type::eof();
1767  else if (!traits_type::eq_int_type(c, traits_type::eof()))
1768  return this->sputc(c);
1769  else
1770  return traits_type::not_eof(c);
1771  }
1772 
1773 
1774  template <typename C, typename T>
1775  int
1777  {
1778  return !exited() && empty_buffer() ? 0 : -1;
1779  }
1780 
1786  template <typename C, typename T>
1787  std::streamsize
1788  basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
1789  {
1790  std::streamsize done = 0;
1791  while (done < n)
1792  {
1793  if (std::streamsize nbuf = this->epptr() - this->pptr())
1794  {
1795  nbuf = std::min(nbuf, n - done);
1796  traits_type::copy(this->pptr(), s + done, nbuf);
1797  this->pbump(nbuf);
1798  done += nbuf;
1799  }
1800  else if (!empty_buffer())
1801  break;
1802  }
1803  return done;
1804  }
1805 
1809  template <typename C, typename T>
1810  bool
1812  {
1813  const std::streamsize count = this->pptr() - this->pbase();
1814  if (count > 0)
1815  {
1816  const std::streamsize written = this->write(this->wbuffer_, count);
1817  if (written > 0)
1818  {
1819  if (const std::streamsize unwritten = count - written)
1820  traits_type::move(this->pbase(), this->pbase()+written, unwritten);
1821  this->pbump(-written);
1822  return true;
1823  }
1824  }
1825  return false;
1826  }
1827 
1835  template <typename C, typename T>
1836  typename basic_pstreambuf<C,T>::int_type
1838  {
1839  if (this->gptr() < this->egptr() || fill_buffer())
1840  return traits_type::to_int_type(*this->gptr());
1841  else
1842  return traits_type::eof();
1843  }
1844 
1853  template <typename C, typename T>
1854  typename basic_pstreambuf<C,T>::int_type
1856  {
1857  if (this->gptr() != this->eback())
1858  {
1859  this->gbump(-1);
1860  if (!traits_type::eq_int_type(c, traits_type::eof()))
1861  *this->gptr() = traits_type::to_char_type(c);
1862  return traits_type::not_eof(c);
1863  }
1864  else
1865  return traits_type::eof();
1866  }
1867 
1868  template <typename C, typename T>
1869  std::streamsize
1871  {
1872  int avail = 0;
1873  if (sizeof(char_type) == 1)
1874  avail = fill_buffer(true) ? this->egptr() - this->gptr() : -1;
1875 #ifdef FIONREAD
1876  else
1877  {
1878  if (::ioctl(rpipe(), FIONREAD, &avail) == -1)
1879  avail = -1;
1880  else if (avail)
1881  avail /= sizeof(char_type);
1882  }
1883 #endif
1884  return std::streamsize(avail);
1885  }
1886 
1890  template <typename C, typename T>
1891  bool
1893  {
1894  const std::streamsize pb1 = this->gptr() - this->eback();
1895  const std::streamsize pb2 = pbsz;
1896  const std::streamsize npb = std::min(pb1, pb2);
1897 
1898  char_type* const rbuf = rbuffer();
1899 
1900  traits_type::move(rbuf + pbsz - npb, this->gptr() - npb, npb);
1901 
1902  std::streamsize rc = -1;
1903 
1904  if (non_blocking)
1905  {
1906  const int flags = ::fcntl(rpipe(), F_GETFL);
1907  if (flags != -1)
1908  {
1909  const bool blocking = !(flags & O_NONBLOCK);
1910  if (blocking)
1911  ::fcntl(rpipe(), F_SETFL, flags | O_NONBLOCK); // set non-blocking
1912 
1913  error_ = 0;
1914  rc = read(rbuf + pbsz, bufsz - pbsz);
1915 
1916  if (rc == -1 && error_ == EAGAIN) // nothing available
1917  rc = 0;
1918  else if (rc == 0) // EOF
1919  rc = -1;
1920 
1921  if (blocking)
1922  ::fcntl(rpipe(), F_SETFL, flags); // restore
1923  }
1924  }
1925  else
1926  rc = read(rbuf + pbsz, bufsz - pbsz);
1927 
1928  if (rc > 0 || (rc == 0 && non_blocking))
1929  {
1930  this->setg( rbuf + pbsz - npb,
1931  rbuf + pbsz,
1932  rbuf + pbsz + rc );
1933  return true;
1934  }
1935  else
1936  {
1937  this->setg(NULL, NULL, NULL);
1938  return false;
1939  }
1940  }
1941 
1949  template <typename C, typename T>
1950  inline std::streamsize
1951  basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n)
1952  {
1953  std::streamsize nwritten = 0;
1954  if (wpipe() >= 0)
1955  {
1956  nwritten = ::write(wpipe(), s, n * sizeof(char_type));
1957  if (nwritten == -1)
1958  error_ = errno;
1959  else
1960  nwritten /= sizeof(char_type);
1961  }
1962  return nwritten;
1963  }
1964 
1972  template <typename C, typename T>
1973  inline std::streamsize
1974  basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
1975  {
1976  std::streamsize nread = 0;
1977  if (rpipe() >= 0)
1978  {
1979  nread = ::read(rpipe(), s, n * sizeof(char_type));
1980  if (nread == -1)
1981  error_ = errno;
1982  else
1983  nread /= sizeof(char_type);
1984  }
1985  return nread;
1986  }
1987 
1989  template <typename C, typename T>
1990  inline pstreams::fd_type&
1992  {
1993  return wpipe_;
1994  }
1995 
1997  template <typename C, typename T>
1998  inline pstreams::fd_type&
2000  {
2001  return rpipe_[rsrc_];
2002  }
2003 
2005  template <typename C, typename T>
2006  inline pstreams::fd_type&
2008  {
2009  return rpipe_[which];
2010  }
2011 
2013  template <typename C, typename T>
2014  inline typename basic_pstreambuf<C,T>::char_type*
2016  {
2017  return rbuffer_[rsrc_];
2018  }
2019 
2020 
2021  /*
2022  * member definitions for pstream_common
2023  */
2024 
2034  template <typename C, typename T>
2035  inline
2037  : std::basic_ios<C,T>(NULL)
2038  , command_()
2039  , buf_()
2040  {
2041  this->std::basic_ios<C,T>::rdbuf(&buf_);
2042  }
2043 
2052  template <typename C, typename T>
2053  inline
2055  : std::basic_ios<C,T>(NULL)
2056  , command_(command)
2057  , buf_()
2058  {
2059  this->std::basic_ios<C,T>::rdbuf(&buf_);
2060  do_open(command, mode);
2061  }
2062 
2072  template <typename C, typename T>
2073  inline
2074  pstream_common<C,T>::pstream_common( const std::string& file,
2075  const argv_type& argv,
2076  pmode mode )
2077  : std::basic_ios<C,T>(NULL)
2078  , command_(file)
2079  , buf_()
2080  {
2081  this->std::basic_ios<C,T>::rdbuf(&buf_);
2082  do_open(file, argv, mode);
2083  }
2084 
2094  template <typename C, typename T>
2095  inline
2097  {
2098  }
2099 
2108  template <typename C, typename T>
2109  inline void
2110  pstream_common<C,T>::do_open(const std::string& command, pmode mode)
2111  {
2112  if (!buf_.open((command_=command), mode))
2113  this->setstate(std::ios_base::failbit);
2114  }
2115 
2125  template <typename C, typename T>
2126  inline void
2127  pstream_common<C,T>::do_open( const std::string& file,
2128  const argv_type& argv,
2129  pmode mode )
2130  {
2131  if (!buf_.open((command_=file), argv, mode))
2132  this->setstate(std::ios_base::failbit);
2133  }
2134 
2136  template <typename C, typename T>
2137  inline void
2139  {
2140  if (!buf_.close())
2141  this->setstate(std::ios_base::failbit);
2142  }
2143 
2148  template <typename C, typename T>
2149  inline bool
2151  {
2152  return buf_.is_open();
2153  }
2154 
2156  template <typename C, typename T>
2157  inline const std::string&
2159  {
2160  return command_;
2161  }
2162 
2164  // TODO document behaviour if buffer replaced.
2165  template <typename C, typename T>
2166  inline typename pstream_common<C,T>::streambuf_type*
2168  {
2169  return const_cast<streambuf_type*>(&buf_);
2170  }
2171 
2172 
2173 #if REDI_EVISCERATE_PSTREAMS
2174 
2206  template <typename C, typename T>
2207  std::size_t
2208  basic_pstreambuf<C,T>::fopen(FILE*& in, FILE*& out, FILE*& err)
2209  {
2210  in = out = err = NULL;
2211  std::size_t open_files = 0;
2212  if (wpipe() > -1)
2213  {
2214  if ((in = ::fdopen(wpipe(), "w")))
2215  {
2216  open_files |= pstdin;
2217  }
2218  }
2219  if (rpipe(rsrc_out) > -1)
2220  {
2221  if ((out = ::fdopen(rpipe(rsrc_out), "r")))
2222  {
2223  open_files |= pstdout;
2224  }
2225  }
2226  if (rpipe(rsrc_err) > -1)
2227  {
2228  if ((err = ::fdopen(rpipe(rsrc_err), "r")))
2229  {
2230  open_files |= pstderr;
2231  }
2232  }
2233  return open_files;
2234  }
2235 
2246  template <typename C, typename T>
2247  inline std::size_t
2248  pstream_common<C,T>::fopen(FILE*& fin, FILE*& fout, FILE*& ferr)
2249  {
2250  return buf_.fopen(fin, fout, ferr);
2251  }
2252 
2253 #endif // REDI_EVISCERATE_PSTREAMS
2254 
2255 
2256 } // namespace redi
2257 
2263 #endif // REDI_PSTREAM_H_SEEN
2264 
2265 // vim: ts=2 sw=2 expandtab
2266 
void close_fd(pstreams::fd_type &fd)
Helper function to close a file descriptor.
Definition: pstream.h:1160
basic_pstream(const std::string &command, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:681
int_type overflow(int_type c)
Transfer characters to the pipe when character buffer overflows.
Definition: pstream.h:1763
std::streamsize write(const char_type *s, std::streamsize n)
Insert a sequence of characters into the pipe.
Definition: pstream.h:1951
int error() const
Return the error number (errno) for the most recent failed operation.
Definition: pstream.h:1695
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:835
fd_type fd_t
Definition: pstream.h:113
~basic_pstream()
Destructor.
Definition: pstream.h:737
fd_type & wpipe()
Return the file descriptor for the output pipe.
Definition: pstream.h:1991
Class template for Bidirectional PStreams.
Definition: pstream.h:648
char_type * rbuffer()
Return the active input buffer.
Definition: pstream.h:2015
Class template for stream buffer.
Definition: pstream.h:101
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:368
std::streamsize read(char_type *s, std::streamsize n)
Extract a sequence of characters from the pipe.
Definition: pstream.h:1974
basic_rpstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:838
void open(const std::string &command, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:918
basic_pstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:666
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:520
bool read_err(bool readerr=true)
Change active input source.
Definition: pstream.h:1740
basic_rpstream(const std::string &command, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:853
virtual ~pstream_common()=0
Pure virtual destructor.
Definition: pstream.h:2096
void close_fd_array(pstreams::fd_type(&fds)[N])
Helper function to close an array of file descriptors.
Definition: pstream.h:1178
std::vector< std::string > argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:82
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:371
pstream_common()
Default constructor.
Definition: pstream.h:2036
int_type underflow()
Transfer characters from the pipe when the character buffer is empty.
Definition: pstream.h:1837
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:934
Class template for common base class.
Definition: pstream.h:277
basic_rpstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:885
basic_ipstream(const argv_type &argv, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:421
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:696
basic_opstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:526
basic_pstreambuf< char > pstreambuf
Type definition for common template specialisation.
Definition: pstream.h:968
static const pmode pstderr
Read from stderr.
Definition: pstream.h:89
streambuf_type * rdbuf() const
Return a pointer to the stream buffer.
Definition: pstream.h:2167
int_type pbackfail(int_type c=traits_type::eof())
Make a character available to be returned by the next extraction.
Definition: pstream.h:1855
Common base class providing constants and typenames.
Definition: pstream.h:76
bool fill_buffer(bool non_blocking=false)
Definition: pstream.h:1892
static const pmode pstdout
Read from stdout.
Definition: pstream.h:88
int sync()
Write any buffered characters to the stream.
Definition: pstream.h:1776
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:868
basic_pstreambuf()
Default constructor.
Definition: pstream.h:1015
basic_ipstream(const std::string &command, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:389
std::string command_
The command used to start the process.
Definition: pstream.h:332
bool exited()
Report whether the process has exited.
Definition: pstream.h:1672
streambuf_type buf_
The stream buffer.
Definition: pstream.h:333
buf_read_src
Enumerated type to indicate whether stdout or stderr is to be read.
Definition: pstream.h:214
basic_pstream & out()
Set streambuf to read from process&#39; stdout.
Definition: pstream.h:777
bool is_open() const
Report whether the stream&#39;s buffer has been initialised.
Definition: pstream.h:2150
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:404
Class template for Input PStreams.
Definition: pstream.h:348
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:663
std::streamsize xsputn(const char_type *s, std::streamsize n)
Insert multiple characters into the pipe.
Definition: pstream.h:1788
pid_t fork(pmode mode)
Initialise pipes and fork process.
Definition: pstream.h:1321
void open(const std::string &command, pmode mode=pstdin)
Start a process.
Definition: pstream.h:609
basic_ipstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:490
basic_pstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:788
basic_opstream(const argv_type &argv, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:573
basic_rpstream< char > rpstream
Type definition for common template specialisation.
Definition: pstream.h:976
basic_ipstream & out()
Set streambuf to read from process&#39; stdout.
Definition: pstream.h:479
void open(const std::string &command, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:749
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:523
All PStreams classes are declared in namespace redi.
int fd_type
Type used for file descriptors.
Definition: pstream.h:85
~basic_pstreambuf()
Destructor.
Definition: pstream.h:1079
basic_pstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:713
std::ios_base::openmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:79
Class template for Restricted PStreams.
Definition: pstream.h:818
basic_pstreambuf * killpg(int signal=SIGTERM)
Send a signal to the process&#39; process group.
Definition: pstream.h:1641
basic_pstreambuf * close()
Close the stream buffer and wait for the process to exit.
Definition: pstream.h:1438
bool is_open() const
Report whether the stream buffer has been initialised.
Definition: pstream.h:1725
bool empty_buffer()
Writes buffered characters to the process&#39; stdin pipe.
Definition: pstream.h:1811
void do_open(const std::string &command, pmode mode)
Start a process.
Definition: pstream.h:2110
~basic_ipstream()
Destructor.
Definition: pstream.h:438
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:832
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:993
basic_ipstream< char > ipstream
Type definition for common template specialisation.
Definition: pstream.h:970
void open(const std::string &command, pmode mode=pstdout)
Start a process.
Definition: pstream.h:451
int wait(bool nohang=false)
Wait for the child process to exit.
Definition: pstream.h:1563
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout)
Start a process.
Definition: pstream.h:467
Class template for Output PStreams.
Definition: pstream.h:508
const std::string & command() const
Return the command used to initialise the stream.
Definition: pstream.h:2158
static const pmode newpg
Create a new process group for the child process.
Definition: pstream.h:92
basic_pstreambuf * open(const std::string &command, pmode mode)
Initialise the stream buffer with command.
Definition: pstream.h:1113
fd_type & rpipe()
Return the file descriptor for the active input pipe.
Definition: pstream.h:1999
istream_type & err()
Obtain a reference to the istream that reads the process&#39; stderr.
Definition: pstream.h:959
basic_ipstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:374
~basic_rpstream()
Destructor.
Definition: pstream.h:906
void close()
Close the pipe.
Definition: pstream.h:2138
void peof()
Close the pipe connected to the process&#39; stdin.
Definition: pstream.h:1706
basic_opstream< char > opstream
Type definition for common template specialisation.
Definition: pstream.h:972
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:660
void open(const std::string &file, const argv_type &argv, pmode mode=pstdin)
Start a process.
Definition: pstream.h:625
int status() const
Return the exit status of the process.
Definition: pstream.h:1685
basic_pstream< char > pstream
Type definition for common template specialisation.
Definition: pstream.h:974
static const pmode pstdin
Write to stdin.
Definition: pstream.h:87
std::streamsize showmanyc()
Report how many characters can be read from active input without blocking.
Definition: pstream.h:1870
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:765
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:556
basic_opstream(const std::string &command, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:541
basic_pstreambuf * kill(int signal=SIGTERM)
Send a signal to the process.
Definition: pstream.h:1606
istream_type & out()
Obtain a reference to the istream that reads the process&#39; stdout.
Definition: pstream.h:947
~basic_opstream()
Destructor.
Definition: pstream.h:597