Acoustic Touch Recognition
pstream.h
Go to the documentation of this file.
1 // PStreams - POSIX Process I/O for C++
2 
3 // Copyright (C) 2001 - 2020 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 // SPDX-License-Identifier: BSL-1.0
9 
19 #ifndef REDI_PSTREAM_H_SEEN
20 #define REDI_PSTREAM_H_SEEN
21 
22 #include <ios>
23 #include <streambuf>
24 #include <istream>
25 #include <ostream>
26 #include <string>
27 #include <vector>
28 #include <algorithm> // for min()
29 #include <cerrno> // for errno
30 #include <cstddef> // for size_t, NULL
31 #include <cstdlib> // for exit()
32 #include <sys/types.h> // for pid_t
33 #include <sys/wait.h> // for waitpid()
34 #include <sys/ioctl.h> // for ioctl() and FIONREAD
35 // #if defined(__sun)
36 // # include <sys/filio.h> // for FIONREAD on Solaris 2.5
37 // #endif
38 #include <unistd.h> // for pipe() fork() exec() and filedes functions
39 #include <signal.h> // for kill()
40 #include <fcntl.h> // for fcntl()
41 #if REDI_EVISCERATE_PSTREAMS
42 # include <stdio.h> // for FILE, fdopen()
43 #endif
44 
45 
47 #define PSTREAMS_VERSION 0x0103 // 1.0.3
48 
62 namespace redi
63 {
65  struct pstreams
66  {
68  typedef std::ios_base::openmode pmode;
69 
71  typedef std::vector<std::string> argv_type;
72 
74  typedef int fd_type;
75 
76  static const pmode pstdin = std::ios_base::out;
77  static const pmode pstdout = std::ios_base::in;
78  static const pmode pstderr = std::ios_base::app;
79 
81  static const pmode newpg = std::ios_base::trunc;
82 
83  protected:
84  enum { bufsz = 32 };
85  enum { pbsz = 2 };
86 
87 #if __cplusplus >= 201103L
88  template<typename T>
89  using stringable = decltype((void)std::string(std::declval<const T&>()));
90 #endif
91  };
92 
94  template <typename CharT, typename Traits = std::char_traits<CharT> >
96  : public std::basic_streambuf<CharT, Traits>
97  , public pstreams
98  {
99  public:
100  // Type definitions for dependent types
101  typedef CharT char_type;
102  typedef Traits traits_type;
103  typedef typename traits_type::int_type int_type;
104  typedef typename traits_type::off_type off_type;
105  typedef typename traits_type::pos_type pos_type;
107  typedef fd_type fd_t;
108 
111 
113  basic_pstreambuf(const std::string& cmd, pmode mode);
114 
116  basic_pstreambuf( const std::string& file,
117  const argv_type& argv,
118  pmode mode );
119 
120 #if __cplusplus >= 201103L
122  basic_pstreambuf& operator=(basic_pstreambuf&&) noexcept;
123  void swap(basic_pstreambuf&) noexcept;
124 #endif
125 
127  ~basic_pstreambuf();
128 
131  open(const std::string& cmd, 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:
257 #if __cplusplus >= 201103L
258  using basic_streambuf = std::basic_streambuf<char_type, traits_type>;
259 #else
261  basic_pstreambuf& operator=(const basic_pstreambuf&);
262 #endif
263 
264  void
265  init_rbuffers();
266 
267  pid_t ppid_; // pid of process
268  fd_type wpipe_; // pipe used to write to process' stdin
269  fd_type rpipe_[2]; // two pipes to read from, stdout and stderr
270  char_type* wbuffer_;
271  char_type* rbuffer_[2];
272  char_type* rbufstate_[3];
275  int status_; // hold exit status of child process
276  int error_; // hold errno if fork() or exec() fails
277  };
278 
280  template <typename CharT, typename Traits = std::char_traits<CharT> >
282  : virtual public std::basic_ios<CharT, Traits>
283  , virtual public pstreams
284  {
285  protected:
287  typedef std::basic_ios<CharT, Traits> ios_type;
288 
291 
293  pstream_common();
294 
296  pstream_common(const std::string& cmd, pmode mode);
297 
299  pstream_common(const std::string& file, const argv_type& argv, pmode mode);
300 
302  virtual
303  ~pstream_common() = 0;
304 
305 #if __cplusplus >= 201103L
306  pstream_common(pstream_common&& rhs) noexcept
307  : command_(std::move(rhs.command_))
308  , buf_(std::move(rhs.buf_))
309  {
310  /* derived class is responsible for ios_type::move(rhs) happening */
311  }
312 
314  operator=(pstream_common&& rhs) noexcept
315  {
316  command_ = std::move(rhs.command_);
317  buf_ = std::move(rhs.buf_);
318  return *this;
319  }
320 
321  void
322  swap(pstream_common& rhs) noexcept
323  {
324  /* derived class is responsible for ios_type::swap(rhs) happening */
325  command_.swap(rhs.command_);
326  buf_.swap(rhs.buf_);
327  }
328 #endif // C++11
329 
331  void
332  do_open(const std::string& cmd, pmode mode);
333 
335  void
336  do_open(const std::string& file, const argv_type& argv, pmode mode);
337 
338  public:
341  int
342  close();
343 
345  bool
346  is_open() const;
347 
349  const std::string&
350  command() const;
351 
353  streambuf_type*
354  rdbuf() const;
355 
356 #if REDI_EVISCERATE_PSTREAMS
357  std::size_t
359  fopen(FILE*& in, FILE*& out, FILE*& err);
360 #endif
361 
362  protected:
363  std::string command_;
364  streambuf_type buf_;
365  };
366 
367 
378  template <typename CharT, typename Traits = std::char_traits<CharT> >
380  : public std::basic_istream<CharT, Traits>
381  , public pstream_common<CharT, Traits>
382  , virtual public pstreams
383  {
384  typedef std::basic_istream<CharT, Traits> istream_type;
386 
387  using pbase_type::buf_; // declare name in this scope
388 
389  // Ensure a basic_ipstream will read from at least one pipe
390  pmode readable(pmode mode)
391  {
392  if (!(mode & (pstdout|pstderr)))
393  mode |= pstdout;
394  return mode;
395  }
396 
397  public:
399  typedef typename pbase_type::pmode pmode;
400 
403 
406  : istream_type(NULL), pbase_type()
407  { }
408 
419  explicit
420  basic_ipstream(const std::string& cmd, pmode mode = pstdout)
421  : istream_type(NULL), pbase_type(cmd, readable(mode))
422  { }
423 
435  basic_ipstream( const std::string& file,
436  const argv_type& argv,
437  pmode mode = pstdout )
438  : istream_type(NULL), pbase_type(file, argv, readable(mode))
439  { }
440 
451  explicit
452  basic_ipstream(const argv_type& argv, pmode mode = pstdout)
453  : istream_type(NULL), pbase_type(argv.at(0), argv, readable(mode))
454  { }
455 
456 #if __cplusplus >= 201103L
457  template<typename T, typename = stringable<T>>
458  explicit
459  basic_ipstream(std::initializer_list<T> args, pmode mode = pstdout)
460  : basic_ipstream(argv_type(args.begin(), args.end()), mode)
461  { }
462 
463  basic_ipstream(basic_ipstream&& rhs)
464  : istream_type(std::move(rhs))
465  , pbase_type(std::move(rhs))
466  { istream_type::set_rdbuf(std::addressof(pbase_type::buf_)); }
467 
468  basic_ipstream&
469  operator=(basic_ipstream&& rhs)
470  {
471  istream_type::operator=(std::move(rhs));
472  pbase_type::operator=(std::move(rhs));
473  return *this;
474  }
475 
476  void
477  swap(basic_ipstream& rhs)
478  {
479  istream_type::swap(rhs);
480  pbase_type::swap(rhs);
481  }
482 #endif // C++11
483 
490  { }
491 
501  void
502  open(const std::string& cmd, pmode mode = pstdout)
503  {
504  this->do_open(cmd, readable(mode));
505  }
506 
517  void
518  open( const std::string& file,
519  const argv_type& argv,
520  pmode mode = pstdout )
521  {
522  this->do_open(file, argv, readable(mode));
523  }
524 
529  basic_ipstream&
530  out()
531  {
532  this->buf_.read_err(false);
533  return *this;
534  }
535 
540  basic_ipstream&
541  err()
542  {
543  this->buf_.read_err(true);
544  return *this;
545  }
546  };
547 
548 
558  template <typename CharT, typename Traits = std::char_traits<CharT> >
560  : public std::basic_ostream<CharT, Traits>
561  , public pstream_common<CharT, Traits>
562  , virtual public pstreams
563  {
564  typedef std::basic_ostream<CharT, Traits> ostream_type;
566 
567  using pbase_type::buf_; // declare name in this scope
568 
569  public:
571  typedef typename pbase_type::pmode pmode;
572 
575 
578  : ostream_type(NULL), pbase_type()
579  { }
580 
591  explicit
592  basic_opstream(const std::string& cmd, pmode mode = pstdin)
593  : ostream_type(NULL), pbase_type(cmd, mode|pstdin)
594  { }
595 
607  basic_opstream( const std::string& file,
608  const argv_type& argv,
609  pmode mode = pstdin )
610  : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
611  { }
612 
623  explicit
624  basic_opstream(const argv_type& argv, pmode mode = pstdin)
625  : ostream_type(NULL), pbase_type(argv.at(0), argv, mode|pstdin)
626  { }
627 
628 #if __cplusplus >= 201103L
629 
636  template<typename T, typename = stringable<T>>
637  explicit
638  basic_opstream(std::initializer_list<T> args, pmode mode = pstdin)
639  : basic_opstream(argv_type(args.begin(), args.end()), mode)
640  { }
641 
642  basic_opstream(basic_opstream&& rhs)
643  : ostream_type(std::move(rhs))
644  , pbase_type(std::move(rhs))
645  { ostream_type::set_rdbuf(std::addressof(pbase_type::buf_)); }
646 
647  basic_opstream&
648  operator=(basic_opstream&& rhs)
649  {
650  ostream_type::operator=(std::move(rhs));
651  pbase_type::operator=(std::move(rhs));
652  return *this;
653  }
654 
655  void
656  swap(basic_opstream& rhs)
657  {
658  ostream_type::swap(rhs);
659  pbase_type::swap(rhs);
660  }
661 #endif // C++11
662 
669 
679  void
680  open(const std::string& cmd, pmode mode = pstdin)
681  {
682  this->do_open(cmd, mode|pstdin);
683  }
684 
695  void
696  open( const std::string& file,
697  const argv_type& argv,
698  pmode mode = pstdin)
699  {
700  this->do_open(file, argv, mode|pstdin);
701  }
702  };
703 
704 
718  template <typename CharT, typename Traits = std::char_traits<CharT> >
720  : public std::basic_iostream<CharT, Traits>
721  , public pstream_common<CharT, Traits>
722  , virtual public pstreams
723  {
724  typedef std::basic_iostream<CharT, Traits> iostream_type;
726 
727  using pbase_type::buf_; // declare name in this scope
728 
729  public:
731  typedef typename pbase_type::pmode pmode;
732 
735 
738  : iostream_type(NULL), pbase_type()
739  { }
740 
751  explicit
752  basic_pstream(const std::string& cmd, pmode mode = pstdout|pstdin)
753  : iostream_type(NULL), pbase_type(cmd, mode)
754  { }
755 
767  basic_pstream( const std::string& file,
768  const argv_type& argv,
769  pmode mode = pstdout|pstdin )
770  : iostream_type(NULL), pbase_type(file, argv, mode)
771  { }
772 
783  explicit
784  basic_pstream(const argv_type& argv, pmode mode = pstdout|pstdin)
785  : iostream_type(NULL), pbase_type(argv.at(0), argv, mode)
786  { }
787 
788 #if __cplusplus >= 201103L
789 
796  template<typename T, typename = stringable<T>>
797  explicit
798  basic_pstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
799  : basic_pstream(argv_type(l.begin(), l.end()), mode)
800  { }
801 
802  basic_pstream(basic_pstream&& rhs)
803  : iostream_type(std::move(rhs))
804  , pbase_type(std::move(rhs))
805  { iostream_type::set_rdbuf(std::addressof(pbase_type::buf_)); }
806 
807  basic_pstream&
808  operator=(basic_pstream&& rhs)
809  {
810  iostream_type::operator=(std::move(rhs));
811  pbase_type::operator=(std::move(rhs));
812  return *this;
813  }
814 
815  void
816  swap(basic_pstream& rhs)
817  {
818  iostream_type::swap(rhs);
819  pbase_type::swap(rhs);
820  }
821 #endif // C++11
822 
829 
839  void
840  open(const std::string& cmd, pmode mode = pstdout|pstdin)
841  {
842  this->do_open(cmd, mode);
843  }
844 
855  void
856  open( const std::string& file,
857  const argv_type& argv,
858  pmode mode = pstdout|pstdin )
859  {
860  this->do_open(file, argv, mode);
861  }
862 
867  basic_pstream&
868  out()
869  {
870  this->buf_.read_err(false);
871  return *this;
872  }
873 
878  basic_pstream&
879  err()
880  {
881  this->buf_.read_err(true);
882  return *this;
883  }
884  };
885 
886 
908  template <typename CharT, typename Traits = std::char_traits<CharT> >
910  : public std::basic_ostream<CharT, Traits>
911  , private std::basic_istream<CharT, Traits>
912  , private pstream_common<CharT, Traits>
913  , virtual public pstreams
914  {
915  typedef std::basic_ostream<CharT, Traits> ostream_type;
916  typedef std::basic_istream<CharT, Traits> istream_type;
918 
919  using pbase_type::buf_; // declare name in this scope
920 
921  public:
923  typedef typename pbase_type::pmode pmode;
924 
927 
930  : ostream_type(NULL), istream_type(NULL), pbase_type()
931  { }
932 
943  explicit
944  basic_rpstream(const std::string& cmd, pmode mode = pstdout|pstdin)
945  : ostream_type(NULL) , istream_type(NULL) , pbase_type(cmd, mode)
946  { }
947 
959  basic_rpstream( const std::string& file,
960  const argv_type& argv,
961  pmode mode = pstdout|pstdin )
962  : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
963  { }
964 
975  explicit
976  basic_rpstream(const argv_type& argv, pmode mode = pstdout|pstdin)
977  : ostream_type(NULL), istream_type(NULL)
978  , pbase_type(argv.at(0), argv, mode)
979  { }
980 
981 #if __cplusplus >= 201103L
982 
989  template<typename T, typename = stringable<T>>
990  explicit
991  basic_rpstream(std::initializer_list<T> l, pmode mode = pstdout|pstdin)
992  : basic_rpstream(argv_type(l.begin(), l.end()), mode)
993  { }
994 
995  // TODO: figure out how to move istream and ostream bases separately,
996  // but so the virtual basic_ios base is only modified once.
997 #if 0
998  basic_rpstream(basic_rpstream&& rhs)
999  : iostream_type(std::move(rhs))
1000  , pbase_type(std::move(rhs))
1001  { iostream_type::set_rdbuf(std::addressof(pbase_type::buf_)); }
1002 
1003  basic_rpstream&
1004  operator=(basic_rpstream&& rhs)
1005  {
1006  iostream_type::operator=(std::move(rhs));
1007  pbase_type::operator=(std::move(rhs));
1008  return *this;
1009  }
1010 
1011  void
1012  swap(basic_rpstream& rhs)
1013  {
1014  iostream_type::swap(rhs);
1015  pbase_type::swap(rhs);
1016  }
1017 #endif
1018 #endif // C++11
1019 
1022 
1032  void
1033  open(const std::string& cmd, pmode mode = pstdout|pstdin)
1034  {
1035  this->do_open(cmd, mode);
1036  }
1037 
1048  void
1049  open( const std::string& file,
1050  const argv_type& argv,
1051  pmode mode = pstdout|pstdin )
1052  {
1053  this->do_open(file, argv, mode);
1054  }
1055 
1061  istream_type&
1063  {
1064  this->buf_.read_err(false);
1065  return *this;
1066  }
1067 
1073  istream_type&
1075  {
1076  this->buf_.read_err(true);
1077  return *this;
1078  }
1079  };
1080 
1081 
1092 
1093 
1106  template <typename C, typename T>
1107  inline std::basic_ostream<C,T>&
1108  peof(std::basic_ostream<C,T>& s)
1109  {
1110  typedef basic_pstreambuf<C,T> pstreambuf_type;
1111  if (pstreambuf_type* p = dynamic_cast<pstreambuf_type*>(s.rdbuf()))
1112  p->peof();
1113  return s;
1114  }
1115 
1116 
1117  /*
1118  * member definitions for pstreambuf
1119  */
1120 
1121 
1128  template <typename C, typename T>
1129  inline
1131  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1132  , wpipe_(-1)
1133  , wbuffer_()
1134  , rbuffer_()
1135  , rbufstate_()
1136  , rsrc_(rsrc_out)
1137  , status_(-1)
1138  , error_(0)
1139  {
1140  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1141  }
1142 
1151  template <typename C, typename T>
1152  inline
1153  basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& cmd, pmode mode)
1154  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1155  , wpipe_(-1)
1156  , wbuffer_()
1157  , rbuffer_()
1158  , rbufstate_()
1159  , rsrc_(rsrc_out)
1160  , status_(-1)
1161  , error_(0)
1162  {
1163  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1164  open(cmd, mode);
1165  }
1166 
1176  template <typename C, typename T>
1177  inline
1179  const argv_type& argv,
1180  pmode mode )
1181  : ppid_(-1) // initialise to -1 to indicate no process run yet.
1182  , wpipe_(-1)
1183  , wbuffer_()
1184  , rbuffer_()
1185  , rbufstate_()
1186  , rsrc_(rsrc_out)
1187  , status_(-1)
1188  , error_(0)
1189  {
1190  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1191  open(file, argv, mode);
1192  }
1193 
1198  template <typename C, typename T>
1199  inline
1201  {
1202  close();
1203  }
1204 
1205 #if __cplusplus >= 201103L
1206 
1209  template <typename C, typename T>
1210  inline
1212  : basic_streambuf(static_cast<const basic_streambuf&>(rhs))
1213  , ppid_(rhs.ppid_)
1214  , wpipe_(rhs.wpipe_)
1215  , rpipe_{rhs.rpipe_[0], rhs.rpipe_[1]}
1216  , wbuffer_(rhs.wbuffer_)
1217  , rbuffer_{rhs.rbuffer_[0], rhs.rbuffer_[1]}
1218  , rbufstate_{rhs.rbufstate_[0], rhs.rbufstate_[1], rhs.rbufstate_[2]}
1219  , rsrc_(rhs.rsrc_)
1220  , status_(rhs.status_)
1221  , error_(rhs.error_)
1222  {
1223  rhs.ppid_ = -1;
1224  rhs.wpipe_ = -1;
1225  rhs.rpipe_[0] = rhs.rpipe_[1] = -1;
1226  rhs.wbuffer_ = nullptr;
1227  rhs.rbuffer_[0] = rhs.rbuffer_[1] = nullptr;
1228  rhs.rbufstate_[0] = rhs.rbufstate_[1] = rhs.rbufstate_[2] = nullptr;
1229  rhs.rsrc_ = rsrc_out;
1230  rhs.status_ = -1;
1231  rhs.error_ = 0;
1232  rhs.setg(nullptr, nullptr, nullptr);
1233  rhs.setp(nullptr, nullptr);
1234  }
1235 
1236  template <typename C, typename T>
1237  inline basic_pstreambuf<C,T>&
1239  {
1240  close();
1241  basic_streambuf::operator=(static_cast<const basic_streambuf&>(rhs));
1242  swap(rhs);
1243  return *this;
1244  }
1245 
1246  template <typename C, typename T>
1247  inline void
1249  {
1250  basic_streambuf::swap(static_cast<basic_streambuf&>(rhs));
1251  std::swap(ppid_, rhs.ppid_);
1252  std::swap(wpipe_, rhs.wpipe_);
1253  std::swap(rpipe_, rhs.rpipe_);
1254  std::swap(wbuffer_, rhs.wbuffer_);
1255  std::swap(rbuffer_, rhs.rbuffer_);
1256  std::swap(rbufstate_, rhs.rbufstate_);
1257  std::swap(rsrc_, rhs.rsrc_);
1258  std::swap(status_, rhs.status_);
1259  std::swap(error_, rhs.error_);
1260  }
1261 #endif // C++11
1262 
1290  template <typename C, typename T>
1292  basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
1293  {
1294  const char * shell_path = "/bin/sh";
1295 #if 0
1296  const std::string argv[] = { "sh", "-c", command };
1297  return this->open(shell_path, argv_type(argv, argv+3), mode);
1298 #else
1299  basic_pstreambuf<C,T>* ret = NULL;
1300 
1301  if (!is_open())
1302  {
1303  switch(fork(mode))
1304  {
1305  case 0 :
1306  // this is the new process, exec command
1307  ::execl(shell_path, "sh", "-c", command.c_str(), (char*)NULL);
1308 
1309  // can only reach this point if exec() failed
1310 
1311  // parent can get exit code from waitpid()
1312  ::_exit(errno);
1313  // using std::exit() would make static dtors run twice
1314 
1315  case -1 :
1316  // couldn't fork, error already handled in pstreambuf::fork()
1317  break;
1318 
1319  default :
1320  // this is the parent process
1321  // activate buffers
1322  create_buffers(mode);
1323  ret = this;
1324  }
1325  }
1326  return ret;
1327 #endif
1328  }
1329 
1338  inline void
1340  {
1341  if (fd >= 0 && ::close(fd) == 0)
1342  fd = -1;
1343  }
1344 
1355  template <int N>
1356  inline void
1358  {
1359  for (std::size_t i = 0; i < N; ++i)
1360  close_fd(fds[i]);
1361  }
1362 
1392  template <typename C, typename T>
1394  basic_pstreambuf<C,T>::open( const std::string& file,
1395  const argv_type& argv,
1396  pmode mode )
1397  {
1398  basic_pstreambuf<C,T>* ret = NULL;
1399 
1400  if (!is_open())
1401  {
1402  // constants for read/write ends of pipe
1403  enum { RD, WR };
1404 
1405  // open another pipe and set close-on-exec
1406  fd_type ck_exec[] = { -1, -1 };
1407  if (-1 == ::pipe(ck_exec)
1408  || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC)
1409  || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC))
1410  {
1411  error_ = errno;
1412  close_fd_array(ck_exec);
1413  }
1414  else
1415  {
1416  switch(fork(mode))
1417  {
1418  case 0 :
1419  // this is the new process, exec command
1420  {
1421  char** arg_v = new char*[argv.size()+1];
1422  for (std::size_t i = 0; i < argv.size(); ++i)
1423  {
1424  const std::string& src = argv[i];
1425  char*& dest = arg_v[i];
1426  dest = new char[src.size()+1];
1427  dest[ src.copy(dest, src.size()) ] = '\0';
1428  }
1429  arg_v[argv.size()] = NULL;
1430 
1431  ::execvp(file.c_str(), arg_v);
1432 
1433  // can only reach this point if exec() failed
1434 
1435  // parent can get error code from ck_exec pipe
1436  error_ = errno;
1437 
1438  while (::write(ck_exec[WR], &error_, sizeof(error_)) == -1
1439  && errno == EINTR)
1440  { }
1441 
1442  ::close(ck_exec[WR]);
1443  ::close(ck_exec[RD]);
1444 
1445  ::_exit(error_);
1446  // using std::exit() would make static dtors run twice
1447  }
1448 
1449  case -1 :
1450  // couldn't fork, error already handled in pstreambuf::fork()
1451  close_fd_array(ck_exec);
1452  break;
1453 
1454  default :
1455  // this is the parent process
1456 
1457  // check child called exec() successfully
1458  ::close(ck_exec[WR]);
1459  switch (::read(ck_exec[RD], &error_, sizeof(error_)))
1460  {
1461  case 0:
1462  // activate buffers
1463  create_buffers(mode);
1464  ret = this;
1465  break;
1466  case -1:
1467  error_ = errno;
1468  break;
1469  default:
1470  // error_ contains error code from child
1471  // call wait() to clean up and set ppid_ to 0
1472  this->wait();
1473  break;
1474  }
1475  ::close(ck_exec[RD]);
1476  }
1477  }
1478  }
1479  return ret;
1480  }
1481 
1498  template <typename C, typename T>
1499  pid_t
1501  {
1502  pid_t pid = -1;
1503 
1504  // Three pairs of file descriptors, for pipes connected to the
1505  // process' stdin, stdout and stderr
1506  // (stored in a single array so close_fd_array() can close all at once)
1507  fd_type fd[] = { -1, -1, -1, -1, -1, -1 };
1508  fd_type* const pin = fd;
1509  fd_type* const pout = fd+2;
1510  fd_type* const perr = fd+4;
1511 
1512  // constants for read/write ends of pipe
1513  enum { RD, WR };
1514 
1515  // N.B.
1516  // For the pstreambuf pin is an output stream and
1517  // pout and perr are input streams.
1518 
1519  if (!error_ && mode&pstdin && ::pipe(pin))
1520  error_ = errno;
1521 
1522  if (!error_ && mode&pstdout && ::pipe(pout))
1523  error_ = errno;
1524 
1525  if (!error_ && mode&pstderr && ::pipe(perr))
1526  error_ = errno;
1527 
1528  if (!error_)
1529  {
1530  pid = ::fork();
1531  switch (pid)
1532  {
1533  case 0 :
1534  {
1535  // this is the new process
1536 
1537  // for each open pipe close one end and redirect the
1538  // respective standard stream to the other end
1539 
1540  if (*pin >= 0)
1541  {
1542  ::close(pin[WR]);
1543  ::dup2(pin[RD], STDIN_FILENO);
1544  ::close(pin[RD]);
1545  }
1546  if (*pout >= 0)
1547  {
1548  ::close(pout[RD]);
1549  ::dup2(pout[WR], STDOUT_FILENO);
1550  ::close(pout[WR]);
1551  }
1552  if (*perr >= 0)
1553  {
1554  ::close(perr[RD]);
1555  ::dup2(perr[WR], STDERR_FILENO);
1556  ::close(perr[WR]);
1557  }
1558 
1559 #ifdef _POSIX_JOB_CONTROL
1560  if (mode&newpg)
1561  ::setpgid(0, 0); // Change to a new process group
1562 #endif
1563 
1564  break;
1565  }
1566  case -1 :
1567  {
1568  // couldn't fork for some reason
1569  error_ = errno;
1570  // close any open pipes
1571  close_fd_array(fd);
1572  break;
1573  }
1574  default :
1575  {
1576  // this is the parent process, store process' pid
1577  ppid_ = pid;
1578 
1579  // store one end of open pipes and close other end
1580  if (*pin >= 0)
1581  {
1582  wpipe_ = pin[WR];
1583  ::close(pin[RD]);
1584  }
1585  if (*pout >= 0)
1586  {
1587  rpipe_[rsrc_out] = pout[RD];
1588  ::close(pout[WR]);
1589  }
1590  if (*perr >= 0)
1591  {
1592  rpipe_[rsrc_err] = perr[RD];
1593  ::close(perr[WR]);
1594  }
1595  }
1596  }
1597  }
1598  else
1599  {
1600  // close any pipes we opened before failure
1601  close_fd_array(fd);
1602  }
1603  return pid;
1604  }
1605 
1615  template <typename C, typename T>
1618  {
1619  const bool running = is_open();
1620 
1621  sync(); // this might call wait() and reap the child process
1622 
1623  // rather than trying to work out whether or not we need to clean up
1624  // just do it anyway, all cleanup functions are safe to call twice.
1625 
1627 
1628  // close pipes before wait() so child gets EOF/SIGPIPE
1629  close_fd(wpipe_);
1631 
1632  do
1633  {
1634  error_ = 0;
1635  } while (wait() == -1 && error() == EINTR);
1636 
1637  return running ? this : NULL;
1638  }
1639 
1644  template <typename C, typename T>
1645 #if __cplusplus >= 201402L && __has_cpp_attribute(deprecated)
1646  [[deprecated]]
1647 #elif __GNUC__
1648  __attribute__((deprecated))
1649 #endif
1650  inline void
1652  {
1653  rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1654  rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
1655  rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
1656  }
1657 
1658  template <typename C, typename T>
1659  void
1661  {
1662  if (mode & pstdin)
1663  {
1664  delete[] wbuffer_;
1665  wbuffer_ = new char_type[bufsz];
1666  this->setp(wbuffer_, wbuffer_ + bufsz);
1667  }
1668  if (mode & pstdout)
1669  {
1670  delete[] rbuffer_[rsrc_out];
1671  rbuffer_[rsrc_out] = new char_type[bufsz];
1672  rsrc_ = rsrc_out;
1673  this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
1674  rbuffer_[rsrc_out] + pbsz);
1675  }
1676  if (mode & pstderr)
1677  {
1678  delete[] rbuffer_[rsrc_err];
1679  rbuffer_[rsrc_err] = new char_type[bufsz];
1680  if (!(mode & pstdout))
1681  {
1682  rsrc_ = rsrc_err;
1683  this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
1684  rbuffer_[rsrc_err] + pbsz);
1685  }
1686  }
1687  }
1688 
1689  template <typename C, typename T>
1690  void
1692  {
1693  if (mode & pstdin)
1694  {
1695  this->setp(NULL, NULL);
1696  delete[] wbuffer_;
1697  wbuffer_ = NULL;
1698  }
1699  if (mode & pstdout)
1700  {
1701  if (rsrc_ == rsrc_out)
1702  this->setg(NULL, NULL, NULL);
1703  delete[] rbuffer_[rsrc_out];
1704  rbuffer_[rsrc_out] = NULL;
1705  }
1706  if (mode & pstderr)
1707  {
1708  if (rsrc_ == rsrc_err)
1709  this->setg(NULL, NULL, NULL);
1710  delete[] rbuffer_[rsrc_err];
1711  rbuffer_[rsrc_err] = NULL;
1712  }
1713  }
1714 
1715  template <typename C, typename T>
1718  {
1719  if (rsrc_ != src)
1720  {
1721  char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
1722  this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
1723  for (std::size_t i = 0; i < 3; ++i)
1724  rbufstate_[i] = tmpbufstate[i];
1725  rsrc_ = src;
1726  }
1727  return rsrc_;
1728  }
1729 
1746  template <typename C, typename T>
1747  int
1749  {
1750  int child_exited = -1;
1751  if (is_open())
1752  {
1753  int exit_status;
1754  switch(::waitpid(ppid_, &exit_status, nohang ? WNOHANG : 0))
1755  {
1756  case 0 :
1757  // nohang was true and process has not exited
1758  child_exited = 0;
1759  break;
1760  case -1 :
1761  error_ = errno;
1762  break;
1763  default :
1764  // process has exited
1765  ppid_ = 0;
1766  status_ = exit_status;
1767  child_exited = 1;
1768  // Close wpipe, would get SIGPIPE if we used it.
1770  close_fd(wpipe_);
1771  // Must free read buffers and pipes on destruction
1772  // or next call to open()/close()
1773  break;
1774  }
1775  }
1776  return child_exited;
1777  }
1778 
1789  template <typename C, typename T>
1790  inline basic_pstreambuf<C,T>*
1792  {
1793  basic_pstreambuf<C,T>* ret = NULL;
1794  if (is_open())
1795  {
1796  if (::kill(ppid_, signal))
1797  error_ = errno;
1798  else
1799  {
1800 #if 0
1801  // TODO call exited() to check for exit and clean up? leave to user?
1802  if (signal==SIGTERM || signal==SIGKILL)
1803  this->exited();
1804 #endif
1805  ret = this;
1806  }
1807  }
1808  return ret;
1809  }
1810 
1824  template <typename C, typename T>
1825  inline basic_pstreambuf<C,T>*
1827  {
1828  basic_pstreambuf<C,T>* ret = NULL;
1829 #ifdef _POSIX_JOB_CONTROL
1830  if (is_open())
1831  {
1832  pid_t pgid = ::getpgid(ppid_);
1833  if (pgid == -1)
1834  error_ = errno;
1835  else if (pgid == ::getpgrp())
1836  error_ = EPERM; // Don't commit suicide
1837  else if (::killpg(pgid, signal))
1838  error_ = errno;
1839  else
1840  ret = this;
1841  }
1842 #else
1843  error_ = ENOTSUP;
1844 #endif
1845  return ret;
1846  }
1847 
1855  template <typename C, typename T>
1856  inline bool
1858  {
1859  return ppid_ == 0 || wait(true)==1;
1860  }
1861 
1862 
1868  template <typename C, typename T>
1869  inline int
1871  {
1872  return status_;
1873  }
1874 
1878  template <typename C, typename T>
1879  inline int
1881  {
1882  return error_;
1883  }
1884 
1889  template <typename C, typename T>
1890  inline void
1892  {
1893  sync();
1895  close_fd(wpipe_);
1896  }
1897 
1908  template <typename C, typename T>
1909  inline bool
1911  {
1912  return ppid_ > 0;
1913  }
1914 
1923  template <typename C, typename T>
1924  inline bool
1926  {
1927  buf_read_src src = readerr ? rsrc_err : rsrc_out;
1928  if (rpipe_[src]>=0)
1929  {
1930  switch_read_buffer(src);
1931  return true;
1932  }
1933  return false;
1934  }
1935 
1946  template <typename C, typename T>
1949  {
1950  if (!empty_buffer())
1951  return traits_type::eof();
1952  else if (!traits_type::eq_int_type(c, traits_type::eof()))
1953  return this->sputc(c);
1954  else
1955  return traits_type::not_eof(c);
1956  }
1957 
1958 
1959  template <typename C, typename T>
1960  int
1962  {
1963  return !exited() && empty_buffer() ? 0 : -1;
1964  }
1965 
1971  template <typename C, typename T>
1972  std::streamsize
1973  basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
1974  {
1975  std::streamsize done = 0;
1976  while (done < n)
1977  {
1978  if (std::streamsize nbuf = this->epptr() - this->pptr())
1979  {
1980  nbuf = std::min(nbuf, n - done);
1981  traits_type::copy(this->pptr(), s + done, nbuf);
1982  this->pbump(nbuf);
1983  done += nbuf;
1984  }
1985  else if (!empty_buffer())
1986  break;
1987  }
1988  return done;
1989  }
1990 
1994  template <typename C, typename T>
1995  bool
1997  {
1998  const std::streamsize count = this->pptr() - this->pbase();
1999  if (count > 0)
2000  {
2001  const std::streamsize written = this->write(this->wbuffer_, count);
2002  if (written > 0)
2003  {
2004  if (const std::streamsize unwritten = count - written)
2005  traits_type::move(this->pbase(), this->pbase()+written, unwritten);
2006  this->pbump(-written);
2007  return true;
2008  }
2009  }
2010  return false;
2011  }
2012 
2020  template <typename C, typename T>
2023  {
2024  if (this->gptr() < this->egptr() || fill_buffer())
2025  return traits_type::to_int_type(*this->gptr());
2026  else
2027  return traits_type::eof();
2028  }
2029 
2038  template <typename C, typename T>
2041  {
2042  if (this->gptr() != this->eback())
2043  {
2044  this->gbump(-1);
2045  if (!traits_type::eq_int_type(c, traits_type::eof()))
2046  *this->gptr() = traits_type::to_char_type(c);
2047  return traits_type::not_eof(c);
2048  }
2049  else
2050  return traits_type::eof();
2051  }
2052 
2053  template <typename C, typename T>
2054  std::streamsize
2056  {
2057  int avail = 0;
2058  if (sizeof(char_type) == 1)
2059  avail = fill_buffer(true) ? this->egptr() - this->gptr() : -1;
2060 #ifdef FIONREAD
2061  else
2062  {
2063  if (::ioctl(rpipe(), FIONREAD, &avail) == -1)
2064  avail = -1;
2065  else if (avail)
2066  avail /= sizeof(char_type);
2067  }
2068 #endif
2069  return std::streamsize(avail);
2070  }
2071 
2075  template <typename C, typename T>
2076  bool
2078  {
2079  const std::streamsize pb1 = this->gptr() - this->eback();
2080  const std::streamsize pb2 = pbsz;
2081  const std::streamsize npb = std::min(pb1, pb2);
2082 
2083  char_type* const rbuf = rbuffer();
2084 
2085  if (npb)
2086  traits_type::move(rbuf + pbsz - npb, this->gptr() - npb, npb);
2087 
2088  std::streamsize rc = -1;
2089 
2090  if (non_blocking)
2091  {
2092  const int flags = ::fcntl(rpipe(), F_GETFL);
2093  if (flags != -1)
2094  {
2095  const bool blocking = !(flags & O_NONBLOCK);
2096  if (blocking)
2097  ::fcntl(rpipe(), F_SETFL, flags | O_NONBLOCK); // set non-blocking
2098 
2099  error_ = 0;
2100  rc = read(rbuf + pbsz, bufsz - pbsz);
2101 
2102  if (rc == -1 && error_ == EAGAIN) // nothing available
2103  rc = 0;
2104  else if (rc == 0) // EOF
2105  rc = -1;
2106 
2107  if (blocking)
2108  ::fcntl(rpipe(), F_SETFL, flags); // restore
2109  }
2110  }
2111  else
2112  rc = read(rbuf + pbsz, bufsz - pbsz);
2113 
2114  if (rc > 0 || (rc == 0 && non_blocking))
2115  {
2116  this->setg( rbuf + pbsz - npb,
2117  rbuf + pbsz,
2118  rbuf + pbsz + rc );
2119  return true;
2120  }
2121  else
2122  {
2123  this->setg(NULL, NULL, NULL);
2124  return false;
2125  }
2126  }
2127 
2135  template <typename C, typename T>
2136  inline std::streamsize
2137  basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n)
2138  {
2139  std::streamsize nwritten = 0;
2140  if (wpipe() >= 0)
2141  {
2142  nwritten = ::write(wpipe(), s, n * sizeof(char_type));
2143  if (nwritten == -1)
2144  error_ = errno;
2145  else
2146  nwritten /= sizeof(char_type);
2147  }
2148  return nwritten;
2149  }
2150 
2158  template <typename C, typename T>
2159  inline std::streamsize
2160  basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
2161  {
2162  std::streamsize nread = 0;
2163  if (rpipe() >= 0)
2164  {
2165  nread = ::read(rpipe(), s, n * sizeof(char_type));
2166  if (nread == -1)
2167  error_ = errno;
2168  else
2169  nread /= sizeof(char_type);
2170  }
2171  return nread;
2172  }
2173 
2175  template <typename C, typename T>
2176  inline pstreams::fd_type&
2178  {
2179  return wpipe_;
2180  }
2181 
2183  template <typename C, typename T>
2184  inline pstreams::fd_type&
2186  {
2187  return rpipe_[rsrc_];
2188  }
2189 
2191  template <typename C, typename T>
2192  inline pstreams::fd_type&
2194  {
2195  return rpipe_[which];
2196  }
2197 
2199  template <typename C, typename T>
2200  inline typename basic_pstreambuf<C,T>::char_type*
2202  {
2203  return rbuffer_[rsrc_];
2204  }
2205 
2206 
2207  /*
2208  * member definitions for pstream_common
2209  */
2210 
2220  template <typename C, typename T>
2221  inline
2223  : std::basic_ios<C,T>(NULL)
2224  , command_()
2225  , buf_()
2226  {
2227  this->std::basic_ios<C,T>::rdbuf(&buf_);
2228  }
2229 
2238  template <typename C, typename T>
2239  inline
2240  pstream_common<C,T>::pstream_common(const std::string& cmd, pmode mode)
2241  : std::basic_ios<C,T>(NULL)
2242  , command_(cmd)
2243  , buf_()
2244  {
2245  this->std::basic_ios<C,T>::rdbuf(&buf_);
2246  do_open(cmd, mode);
2247  }
2248 
2258  template <typename C, typename T>
2259  inline
2260  pstream_common<C,T>::pstream_common( const std::string& file,
2261  const argv_type& argv,
2262  pmode mode )
2263  : std::basic_ios<C,T>(NULL)
2264  , command_(file)
2265  , buf_()
2266  {
2267  this->std::basic_ios<C,T>::rdbuf(&buf_);
2268  do_open(file, argv, mode);
2269  }
2270 
2280  template <typename C, typename T>
2281  inline
2283  {
2284  }
2285 
2294  template <typename C, typename T>
2295  inline void
2296  pstream_common<C,T>::do_open(const std::string& cmd, pmode mode)
2297  {
2298  if (!buf_.open((command_=cmd), mode))
2299  this->setstate(std::ios_base::failbit);
2300  }
2301 
2311  template <typename C, typename T>
2312  inline void
2313  pstream_common<C,T>::do_open( const std::string& file,
2314  const argv_type& argv,
2315  pmode mode )
2316  {
2317  if (!buf_.open((command_=file), argv, mode))
2318  this->setstate(std::ios_base::failbit);
2319  }
2320 
2323  template <typename C, typename T>
2324  inline int
2326  {
2327  if (!buf_.close())
2328  this->setstate(std::ios_base::failbit);
2329  return buf_.status();
2330  }
2331 
2336  template <typename C, typename T>
2337  inline bool
2339  {
2340  return buf_.is_open();
2341  }
2342 
2344  template <typename C, typename T>
2345  inline const std::string&
2347  {
2348  return command_;
2349  }
2350 
2352  // TODO document behaviour if buffer replaced.
2353  template <typename C, typename T>
2354  inline typename pstream_common<C,T>::streambuf_type*
2356  {
2357  return const_cast<streambuf_type*>(&buf_);
2358  }
2359 
2360 
2361 #if REDI_EVISCERATE_PSTREAMS
2362 
2394  template <typename C, typename T>
2395  std::size_t
2396  basic_pstreambuf<C,T>::fopen(FILE*& in, FILE*& out, FILE*& err)
2397  {
2398  in = out = err = NULL;
2399  std::size_t open_files = 0;
2400  if (wpipe() > -1)
2401  {
2402  if ((in = ::fdopen(wpipe(), "w")))
2403  {
2404  open_files |= pstdin;
2405  }
2406  }
2407  if (rpipe(rsrc_out) > -1)
2408  {
2409  if ((out = ::fdopen(rpipe(rsrc_out), "r")))
2410  {
2411  open_files |= pstdout;
2412  }
2413  }
2414  if (rpipe(rsrc_err) > -1)
2415  {
2416  if ((err = ::fdopen(rpipe(rsrc_err), "r")))
2417  {
2418  open_files |= pstderr;
2419  }
2420  }
2421  return open_files;
2422  }
2423 
2434  template <typename C, typename T>
2435  inline std::size_t
2436  pstream_common<C,T>::fopen(FILE*& fin, FILE*& fout, FILE*& ferr)
2437  {
2438  return buf_.fopen(fin, fout, ferr);
2439  }
2440 
2441 #endif // REDI_EVISCERATE_PSTREAMS
2442 
2443 
2444 } // namespace redi
2445 
2446 #endif // REDI_PSTREAM_H_SEEN
2447 
2448 // vim: ts=2 sw=2 expandtab
2449 
void close_fd(pstreams::fd_type &fd)
Helper function to close a file descriptor.
Definition: pstream.h:1339
char_type * rbufstate_[3]
Definition: pstream.h:272
buf_read_src switch_read_buffer(buf_read_src)
Definition: pstream.h:1717
int_type overflow(int_type c)
Transfer characters to the pipe when character buffer overflows.
Definition: pstream.h:1948
std::streamsize write(const char_type *s, std::streamsize n)
Insert a sequence of characters into the pipe.
Definition: pstream.h:2137
void open(const std::string &cmd, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:1033
basic_opstream(const std::string &cmd, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:592
void create_buffers(pmode mode)
Definition: pstream.h:1660
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:926
fd_type fd_t
Definition: pstream.h:107
pmode readable(pmode mode)
Definition: pstream.h:390
~basic_pstream()
Destructor.
Definition: pstream.h:828
fd_type & wpipe()
Return the file descriptor for the output pipe.
Definition: pstream.h:2177
Class template for Bidirectional PStreams.
Definition: pstream.h:719
char_type * rbuffer()
Return the active input buffer.
Definition: pstream.h:2201
Class template for stream buffer.
Definition: pstream.h:95
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:399
bool is_open() const
Report whether the stream buffer has been initialised.
Definition: pstream.h:1910
std::streamsize read(char_type *s, std::streamsize n)
Extract a sequence of characters from the pipe.
Definition: pstream.h:2160
traits_type::int_type int_type
Definition: pstream.h:103
basic_rpstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:929
basic_pstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:737
int error() const
Return the error number (errno) for the most recent failed operation.
Definition: pstream.h:1880
std::basic_istream< CharT, Traits > istream_type
Definition: pstream.h:384
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:571
const std::string & command() const
Return the command used to initialise the stream.
Definition: pstream.h:2346
bool read_err(bool readerr=true)
Change active input source.
Definition: pstream.h:1925
pstream_common< CharT, Traits > pbase_type
Definition: pstream.h:917
fd_type rpipe_[2]
Definition: pstream.h:269
virtual ~pstream_common()=0
Pure virtual destructor.
Definition: pstream.h:2282
void close_fd_array(pstreams::fd_type(&fds)[N])
Helper function to close an array of file descriptors.
Definition: pstream.h:1357
traits_type::pos_type pos_type
Definition: pstream.h:105
pstream_common< CharT, Traits > pbase_type
Definition: pstream.h:385
std::vector< std::string > argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:71
Definition: pstream.h:84
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:402
pstream_common()
Default constructor.
Definition: pstream.h:2222
int_type underflow()
Transfer characters from the pipe when the character buffer is empty.
Definition: pstream.h:2022
void open(const std::string &cmd, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:840
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:1049
CharT char_type
Definition: pstream.h:101
Class template for common base class.
Definition: pstream.h:281
basic_rpstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:976
basic_ipstream(const argv_type &argv, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:452
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:767
basic_opstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:577
basic_pstreambuf< char > pstreambuf
Type definition for common template specialisation.
Definition: pstream.h:1083
int status_
Definition: pstream.h:275
basic_ipstream(const std::string &cmd, pmode mode=pstdout)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:420
static const pmode pstderr
Read from stderr.
Definition: pstream.h:78
int status() const
Return the exit status of the process.
Definition: pstream.h:1870
int_type pbackfail(int_type c=traits_type::eof())
Make a character available to be returned by the next extraction.
Definition: pstream.h:2040
void destroy_buffers(pmode mode)
Definition: pstream.h:1691
Common base class providing constants and typenames.
Definition: pstream.h:65
void open(const std::string &cmd, pmode mode=pstdout)
Start a process.
Definition: pstream.h:502
bool fill_buffer(bool non_blocking=false)
Definition: pstream.h:2077
static const pmode pstdout
Read from stdout.
Definition: pstream.h:77
pstreams::pmode pmode
Definition: pstream.h:289
int sync()
Write any buffered characters to the stream.
Definition: pstream.h:1961
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:959
basic_pstreambuf()
Default constructor.
Definition: pstream.h:1130
pstream_common< CharT, Traits > pbase_type
Definition: pstream.h:565
std::string command_
The command used to start the process.
Definition: pstream.h:363
char_type * wbuffer_
Definition: pstream.h:270
bool exited()
Report whether the process has exited.
Definition: pstream.h:1857
bool is_open() const
Report whether the stream&#39;s buffer has been initialised.
Definition: pstream.h:2338
streambuf_type buf_
The stream buffer.
Definition: pstream.h:364
int close()
Definition: pstream.h:2325
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:868
basic_pstream(const std::string &cmd, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:752
basic_pstreambuf * open(const std::string &cmd, pmode mode)
Initialise the stream buffer with cmd.
Definition: pstream.h:1292
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:435
Class template for Input PStreams.
Definition: pstream.h:379
pstreams::argv_type argv_type
Definition: pstream.h:290
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:734
std::streamsize xsputn(const char_type *s, std::streamsize n)
Insert multiple characters into the pipe.
Definition: pstream.h:1973
pid_t fork(pmode mode)
Initialise pipes and fork process.
Definition: pstream.h:1500
std::basic_istream< CharT, Traits > istream_type
Definition: pstream.h:916
basic_ipstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:541
basic_pstream & err()
Set streambuf to read from process&#39; stderr.
Definition: pstream.h:879
std::basic_iostream< CharT, Traits > iostream_type
Definition: pstream.h:724
basic_opstream(const argv_type &argv, pmode mode=pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:624
basic_rpstream< char > rpstream
Type definition for common template specialisation.
Definition: pstream.h:1091
basic_ipstream & out()
Set streambuf to read from process&#39; stdout.
Definition: pstream.h:530
pbase_type::argv_type argv_type
Type used to hold the arguments for a command.
Definition: pstream.h:574
All PStreams classes are declared in namespace redi.
Definition: pstream.h:85
basic_pstreambuf & operator=(const basic_pstreambuf &)
basic_pstreambuf< CharT, Traits > streambuf_type
Definition: pstream.h:286
int fd_type
Type used for file descriptors.
Definition: pstream.h:74
streambuf_type * rdbuf() const
Return a pointer to the stream buffer.
Definition: pstream.h:2355
~basic_pstreambuf()
Destructor.
Definition: pstream.h:1200
basic_pstream(const argv_type &argv, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:784
Traits traits_type
Definition: pstream.h:102
std::ios_base::openmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:68
Class template for Restricted PStreams.
Definition: pstream.h:909
basic_pstreambuf * killpg(int signal=SIGTERM)
Send a signal to the process&#39; process group.
Definition: pstream.h:1826
basic_pstreambuf * close()
Close the stream buffer and wait for the process to exit.
Definition: pstream.h:1617
bool empty_buffer()
Writes buffered characters to the process&#39; stdin pipe.
Definition: pstream.h:1996
void open(const std::string &cmd, pmode mode=pstdin)
Start a process.
Definition: pstream.h:680
std::basic_ostream< CharT, Traits > ostream_type
Definition: pstream.h:564
~basic_ipstream()
Destructor.
Definition: pstream.h:489
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:923
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:1108
std::basic_ios< CharT, Traits > ios_type
Definition: pstream.h:287
basic_ipstream< char > ipstream
Type definition for common template specialisation.
Definition: pstream.h:1085
fd_type wpipe_
Definition: pstream.h:268
int wait(bool nohang=false)
Wait for the child process to exit.
Definition: pstream.h:1748
pstream_common< CharT, Traits > pbase_type
Definition: pstream.h:725
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout)
Start a process.
Definition: pstream.h:518
buf_read_src rsrc_
Index into rpipe_[] to indicate active source for read operations.
Definition: pstream.h:274
Class template for Output PStreams.
Definition: pstream.h:559
static const pmode newpg
Create a new process group for the child process.
Definition: pstream.h:81
std::basic_ostream< CharT, Traits > ostream_type
Definition: pstream.h:915
fd_type & rpipe()
Return the file descriptor for the active input pipe.
Definition: pstream.h:2185
void do_open(const std::string &cmd, pmode mode)
Start a process.
Definition: pstream.h:2296
istream_type & err()
Obtain a reference to the istream that reads the process&#39; stderr.
Definition: pstream.h:1074
basic_ipstream()
Default constructor, creates an uninitialised stream.
Definition: pstream.h:405
~basic_rpstream()
Destructor.
Definition: pstream.h:1021
void peof()
Close the pipe connected to the process&#39; stdin.
Definition: pstream.h:1891
basic_opstream< char > opstream
Type definition for common template specialisation.
Definition: pstream.h:1087
pbase_type::pmode pmode
Type used to specify how to connect to the process.
Definition: pstream.h:731
void open(const std::string &file, const argv_type &argv, pmode mode=pstdin)
Start a process.
Definition: pstream.h:696
pid_t ppid_
Definition: pstream.h:267
Definition: pstream.h:214
void init_rbuffers()
Definition: pstream.h:1651
basic_pstream< char > pstream
Type definition for common template specialisation.
Definition: pstream.h:1089
traits_type::off_type off_type
Definition: pstream.h:104
static const pmode pstdin
Write to stdin.
Definition: pstream.h:76
std::streamsize showmanyc()
Report how many characters can be read from active input without blocking.
Definition: pstream.h:2055
void open(const std::string &file, const argv_type &argv, pmode mode=pstdout|pstdin)
Start a process.
Definition: pstream.h:856
Definition: pstream.h:214
basic_rpstream(const std::string &cmd, pmode mode=pstdout|pstdin)
Constructor that initialises the stream by starting a process.
Definition: pstream.h:944
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:607
basic_pstreambuf * kill(int signal=SIGTERM)
Send a signal to the process.
Definition: pstream.h:1791
istream_type & out()
Obtain a reference to the istream that reads the process&#39; stdout.
Definition: pstream.h:1062
char_type * rbuffer_[2]
Definition: pstream.h:271
~basic_opstream()
Destructor.
Definition: pstream.h:668
int error_
Definition: pstream.h:276