00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00031 #ifndef REDI_PSTREAM_H_SEEN
00032 #define REDI_PSTREAM_H_SEEN
00033
00034 #include <ios>
00035 #include <streambuf>
00036 #include <istream>
00037 #include <ostream>
00038 #include <string>
00039 #include <vector>
00040 #include <algorithm>
00041 #include <cstring>
00042 #include <cerrno>
00043 #include <cstddef>
00044 #include <cstdlib>
00045 #include <sys/types.h>
00046 #include <sys/wait.h>
00047 #include <unistd.h>
00048 #include <signal.h>
00049 #if REDI_EVISCERATE_PSTREAMS
00050 #include <stdio.h>
00051 #endif
00052
00053
00055 #define PSTREAMS_VERSION 0x0050 // 0.5.0
00056
00070 namespace redi
00071 {
00073 struct pstreams
00074 {
00076 typedef std::ios_base::openmode pmode;
00077
00079 typedef std::vector<std::string> argv_type;
00080
00081 static const pmode pstdin = std::ios_base::out;
00082 static const pmode pstdout = std::ios_base::in;
00083 static const pmode pstderr = std::ios_base::app;
00084
00085 protected:
00086 enum { bufsz = 32 };
00087 enum { pbsz = 2 };
00088 };
00089
00091 template <typename CharT, typename Traits = std::char_traits<CharT> >
00092 class basic_pstreambuf
00093 : public std::basic_streambuf<CharT, Traits>
00094 , public pstreams
00095 {
00096 public:
00097
00098 typedef CharT char_type;
00099 typedef Traits traits_type;
00100 typedef typename traits_type::int_type int_type;
00101 typedef typename traits_type::off_type off_type;
00102 typedef typename traits_type::pos_type pos_type;
00104 typedef int fd_type;
00106 typedef fd_type fd_t;
00107
00109 basic_pstreambuf();
00110
00112 basic_pstreambuf(const std::string& command, pmode mode);
00113
00115 basic_pstreambuf( const std::string& file,
00116 const argv_type& argv,
00117 pmode mode );
00118
00120 ~basic_pstreambuf();
00121
00123 basic_pstreambuf*
00124 open(const std::string& command, pmode mode);
00125
00127 basic_pstreambuf*
00128 open(const std::string& file, const argv_type& argv, pmode mode);
00129
00131 basic_pstreambuf*
00132 close();
00133
00135 basic_pstreambuf*
00136 kill(int signal = SIGTERM);
00137
00139 void
00140 peof();
00141
00143 bool
00144 read_err(bool readerr = true);
00145
00147 bool
00148 is_open() const;
00149
00151 bool
00152 exited();
00153
00154 #if REDI_EVISCERATE_PSTREAMS
00155
00156 std::size_t
00157 fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
00158 #endif
00159
00161 int
00162 status() const;
00163
00165 int
00166 error() const;
00167
00168 protected:
00170 int_type
00171 overflow(int_type c);
00172
00174 int_type
00175 underflow();
00176
00178 int_type
00179 pbackfail(int_type c = traits_type::eof());
00180
00182 int
00183 sync();
00184
00186 std::streamsize
00187 xsputn(const char_type* s, std::streamsize n);
00188
00190 std::streamsize
00191 write(char_type* s, std::streamsize n);
00192
00194 std::streamsize
00195 read(char_type* s, std::streamsize n);
00196
00197 protected:
00199 enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
00200
00202 pid_t
00203 fork(pmode mode);
00204
00206 int
00207 wait(bool nohang = false);
00208
00210 fd_type&
00211 wpipe();
00212
00214 fd_type&
00215 rpipe();
00216
00218 fd_type&
00219 rpipe(buf_read_src which);
00220
00221 void
00222 create_buffers(pmode mode);
00223
00224 void
00225 destroy_buffers(pmode mode);
00226
00228 bool
00229 empty_buffer();
00230
00231 bool
00232 fill_buffer();
00233
00235 char_type*
00236 rbuffer();
00237
00238 buf_read_src
00239 switch_read_buffer(buf_read_src);
00240
00241 private:
00242 basic_pstreambuf(const basic_pstreambuf&);
00243 basic_pstreambuf& operator=(const basic_pstreambuf&);
00244
00245 void
00246 init_rbuffers();
00247
00248 pid_t ppid_;
00249 fd_type wpipe_;
00250 fd_type rpipe_[2];
00251 char_type* wbuffer_;
00252 char_type* rbuffer_[2];
00253 char_type* rbufstate_[3];
00255 buf_read_src rsrc_;
00256 int status_;
00257 int error_;
00258 };
00259
00261 template <typename CharT, typename Traits = std::char_traits<CharT> >
00262 class pstream_common
00263 : virtual public std::basic_ios<CharT, Traits>
00264 , virtual public pstreams
00265 {
00266 protected:
00267 typedef basic_pstreambuf<CharT, Traits> streambuf_type;
00268
00270 pstream_common();
00271
00273 pstream_common(const std::string& command, pmode mode);
00274
00276 pstream_common( const std::string& file,
00277 const argv_type& argv,
00278 pmode mode );
00279
00281 virtual
00282 ~pstream_common() = 0;
00283
00285 void
00286 do_open(const std::string& command, pmode mode);
00287
00289 void
00290 do_open(const std::string& file, const argv_type& argv, pmode mode);
00291
00292 public:
00294 void
00295 close();
00296
00298 bool
00299 is_open() const;
00300
00302 const std::string&
00303 command() const;
00304
00306 streambuf_type*
00307 rdbuf() const;
00308
00309 #if REDI_EVISCERATE_PSTREAMS
00310
00311 std::size_t
00312 fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
00313 #endif
00314
00315 protected:
00316 std::string command_;
00317 streambuf_type buf_;
00318 };
00319
00320
00331 template <typename CharT, typename Traits = std::char_traits<CharT> >
00332 class basic_ipstream
00333 : public std::basic_istream<CharT, Traits>
00334 , public pstream_common<CharT, Traits>
00335 , virtual public pstreams
00336 {
00337 typedef std::basic_istream<CharT, Traits> istream_type;
00338 typedef pstream_common<CharT, Traits> pbase_type;
00339
00340 using pbase_type::buf_;
00341
00342 public:
00344 typedef typename pbase_type::pmode pmode;
00345
00347 typedef typename pbase_type::argv_type argv_type;
00348
00350 basic_ipstream()
00351 : istream_type(NULL), pbase_type()
00352 { }
00353
00364 basic_ipstream(const std::string& command, pmode mode = pstdout)
00365 : istream_type(NULL), pbase_type(command, mode|pstdout)
00366 { }
00367
00379 basic_ipstream( const std::string& file,
00380 const argv_type& argv,
00381 pmode mode = pstdout )
00382 : istream_type(NULL), pbase_type(file, argv, mode|pstdout)
00383 { }
00384
00390 ~basic_ipstream()
00391 { }
00392
00402 void
00403 open(const std::string& command, pmode mode = pstdout)
00404 {
00405 this->do_open(command, mode|pstdout);
00406 }
00407
00418 void
00419 open( const std::string& file,
00420 const argv_type& argv,
00421 pmode mode = pstdout )
00422 {
00423 this->do_open(file, argv, mode|pstdout);
00424 }
00425
00430 basic_ipstream&
00431 out()
00432 {
00433 this->buf_.read_err(false);
00434 return *this;
00435 }
00436
00441 basic_ipstream&
00442 err()
00443 {
00444 this->buf_.read_err(true);
00445 return *this;
00446 }
00447 };
00448
00449
00459 template <typename CharT, typename Traits = std::char_traits<CharT> >
00460 class basic_opstream
00461 : public std::basic_ostream<CharT, Traits>
00462 , public pstream_common<CharT, Traits>
00463 , virtual public pstreams
00464 {
00465 typedef std::basic_ostream<CharT, Traits> ostream_type;
00466 typedef pstream_common<CharT, Traits> pbase_type;
00467
00468 using pbase_type::buf_;
00469
00470 public:
00472 typedef typename pbase_type::pmode pmode;
00473
00475 typedef typename pbase_type::argv_type argv_type;
00476
00478 basic_opstream()
00479 : ostream_type(NULL), pbase_type()
00480 { }
00481
00492 basic_opstream(const std::string& command, pmode mode = pstdin)
00493 : ostream_type(NULL), pbase_type(command, mode|pstdin)
00494 { }
00495
00507 basic_opstream( const std::string& file,
00508 const argv_type& argv,
00509 pmode mode = pstdin )
00510 : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
00511 { }
00512
00518 ~basic_opstream() { }
00519
00529 void
00530 open(const std::string& command, pmode mode = pstdin)
00531 {
00532 this->do_open(command, mode|pstdin);
00533 }
00534
00545 void
00546 open( const std::string& file,
00547 const argv_type& argv,
00548 pmode mode = pstdin)
00549 {
00550 this->do_open(file, argv, mode|pstdin);
00551 }
00552 };
00553
00554
00568 template <typename CharT, typename Traits = std::char_traits<CharT> >
00569 class basic_pstream
00570 : public std::basic_iostream<CharT, Traits>
00571 , public pstream_common<CharT, Traits>
00572 , virtual public pstreams
00573 {
00574 typedef std::basic_iostream<CharT, Traits> iostream_type;
00575 typedef pstream_common<CharT, Traits> pbase_type;
00576
00577 using pbase_type::buf_;
00578
00579 public:
00581 typedef typename pbase_type::pmode pmode;
00582
00584 typedef typename pbase_type::argv_type argv_type;
00585
00587 basic_pstream()
00588 : iostream_type(NULL), pbase_type()
00589 { }
00590
00601 basic_pstream( const std::string& command,
00602 pmode mode = pstdout|pstdin )
00603 : iostream_type(NULL), pbase_type(command, mode)
00604 { }
00605
00617 basic_pstream( const std::string& file,
00618 const argv_type& argv,
00619 pmode mode = pstdout|pstdin )
00620 : iostream_type(NULL), pbase_type(file, argv, mode)
00621 { }
00622
00628 ~basic_pstream() { }
00629
00639 void
00640 open(const std::string& command, pmode mode = pstdout|pstdin)
00641 {
00642 this->do_open(command, mode);
00643 }
00644
00655 void
00656 open( const std::string& file,
00657 const argv_type& argv,
00658 pmode mode = pstdout|pstdin )
00659 {
00660 this->do_open(file, argv, mode);
00661 }
00662
00667 basic_pstream&
00668 out()
00669 {
00670 this->buf_.read_err(false);
00671 return *this;
00672 }
00673
00678 basic_pstream&
00679 err()
00680 {
00681 this->buf_.read_err(true);
00682 return *this;
00683 }
00684 };
00685
00686
00708 template <typename CharT, typename Traits = std::char_traits<CharT> >
00709 class basic_rpstream
00710 : public std::basic_ostream<CharT, Traits>
00711 , private std::basic_istream<CharT, Traits>
00712 , private pstream_common<CharT, Traits>
00713 , virtual public pstreams
00714 {
00715 typedef std::basic_ostream<CharT, Traits> ostream_type;
00716 typedef std::basic_istream<CharT, Traits> istream_type;
00717 typedef pstream_common<CharT, Traits> pbase_type;
00718
00719 using pbase_type::buf_;
00720
00721 public:
00723 typedef typename pbase_type::pmode pmode;
00724
00726 typedef typename pbase_type::argv_type argv_type;
00727
00729 basic_rpstream()
00730 : ostream_type(NULL) , istream_type(NULL) , pbase_type()
00731 { }
00732
00743 basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin)
00744 : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode)
00745 { }
00746
00758 basic_rpstream( const std::string& file,
00759 const argv_type& argv,
00760 pmode mode = pstdout|pstdin )
00761 : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
00762 { }
00763
00765 ~basic_rpstream() { }
00766
00776 void
00777 open(const std::string& command, pmode mode = pstdout|pstdin)
00778 {
00779 this->do_open(command, mode);
00780 }
00781
00792 void
00793 open( const std::string& file,
00794 const argv_type& argv,
00795 pmode mode = pstdout|pstdin )
00796 {
00797 this->do_open(file, argv, mode);
00798 }
00799
00805 istream_type&
00806 out()
00807 {
00808 this->buf_.read_err(false);
00809 return *this;
00810 }
00811
00817 istream_type&
00818 err()
00819 {
00820 this->buf_.read_err(true);
00821 return *this;
00822 }
00823 };
00824
00825
00827 typedef basic_pstreambuf<char> pstreambuf;
00829 typedef basic_ipstream<char> ipstream;
00831 typedef basic_opstream<char> opstream;
00833 typedef basic_pstream<char> pstream;
00835 typedef basic_rpstream<char> rpstream;
00836
00837
00850 template <typename C, typename T>
00851 inline std::basic_ostream<C,T>&
00852 peof(std::basic_ostream<C,T>& s)
00853 {
00854 typedef basic_pstreambuf<C,T> pstreambuf;
00855 if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf()))
00856 p->peof();
00857 return s;
00858 }
00859
00860
00861
00862
00863
00864
00865
00872 template <typename C, typename T>
00873 inline
00874 basic_pstreambuf<C,T>::basic_pstreambuf()
00875 : ppid_(-1)
00876 , wpipe_(-1)
00877 , wbuffer_(NULL)
00878 , rsrc_(rsrc_out)
00879 , status_(-1)
00880 , error_(0)
00881 {
00882 init_rbuffers();
00883 }
00884
00893 template <typename C, typename T>
00894 inline
00895 basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode)
00896 : ppid_(-1)
00897 , wpipe_(-1)
00898 , wbuffer_(NULL)
00899 , rsrc_(rsrc_out)
00900 , status_(-1)
00901 , error_(0)
00902 {
00903 init_rbuffers();
00904 open(command, mode);
00905 }
00906
00916 template <typename C, typename T>
00917 inline
00918 basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& file,
00919 const argv_type& argv,
00920 pmode mode )
00921 : ppid_(-1)
00922 , wpipe_(-1)
00923 , wbuffer_(NULL)
00924 , rsrc_(rsrc_out)
00925 , status_(-1)
00926 , error_(0)
00927 {
00928 init_rbuffers();
00929 open(file, argv, mode);
00930 }
00931
00936 template <typename C, typename T>
00937 inline
00938 basic_pstreambuf<C,T>::~basic_pstreambuf()
00939 {
00940 close();
00941 }
00942
00957 template <typename C, typename T>
00958 basic_pstreambuf<C,T>*
00959 basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
00960 {
00961 basic_pstreambuf<C,T>* ret = NULL;
00962
00963 if (!is_open())
00964 {
00965 switch(fork(mode))
00966 {
00967 case 0 :
00968 {
00969
00970 ::execlp("sh", "sh", "-c", command.c_str(), (void*)NULL);
00971
00972
00973
00974
00975 ::_exit(errno);
00976
00977 }
00978 case -1 :
00979 {
00980
00981 break;
00982 }
00983 default :
00984 {
00985
00986
00987 create_buffers(mode);
00988 ret = this;
00989 }
00990 }
00991 }
00992 return ret;
00993 }
00994
01011 template <typename C, typename T>
01012 basic_pstreambuf<C,T>*
01013 basic_pstreambuf<C,T>::open( const std::string& file,
01014 const argv_type& argv,
01015 pmode mode )
01016 {
01017 basic_pstreambuf<C,T>* ret = NULL;
01018
01019 if (!is_open())
01020 {
01021 switch(fork(mode))
01022 {
01023 case 0 :
01024 {
01025
01026
01027 char** arg_v = new char*[argv.size()+1];
01028 for (std::size_t i = 0; i < argv.size(); ++i)
01029 {
01030 const std::string& src = argv[i];
01031 char*& dest = arg_v[i];
01032 dest = new char[src.size()+1];
01033 dest[ src.copy(dest, src.size()) ] = '\0';
01034 }
01035 arg_v[argv.size()] = NULL;
01036
01037 ::execvp(file.c_str(), arg_v);
01038
01039
01040
01041
01042 ::_exit(errno);
01043
01044 }
01045 case -1 :
01046 {
01047
01048 break;
01049 }
01050 default :
01051 {
01052
01053
01054 create_buffers(mode);
01055 ret = this;
01056 }
01057 }
01058 }
01059 return ret;
01060 }
01061
01071 inline void
01072 close_fd_array(int* filedes, std::size_t count)
01073 {
01074 for (std::size_t i = 0; i < count; ++i)
01075 if (filedes[i] >= 0)
01076 if (::close(filedes[i]) == 0)
01077 filedes[i] = -1;
01078 }
01079
01096 template <typename C, typename T>
01097 pid_t
01098 basic_pstreambuf<C,T>::fork(pmode mode)
01099 {
01100 pid_t pid = -1;
01101
01102
01103
01104
01105 fd_type fd[6] = {-1, -1, -1, -1, -1, -1};
01106 fd_type* const pin = fd;
01107 fd_type* const pout = fd+2;
01108 fd_type* const perr = fd+4;
01109
01110
01111 const int RD = 0;
01112 const int WR = 1;
01113
01114
01115
01116
01117
01118 if (!error_ && mode&pstdin && ::pipe(pin))
01119 error_ = errno;
01120
01121 if (!error_ && mode&pstdout && ::pipe(pout))
01122 error_ = errno;
01123
01124 if (!error_ && mode&pstderr && ::pipe(perr))
01125 error_ = errno;
01126
01127 if (!error_)
01128 {
01129 pid = ::fork();
01130 switch (pid)
01131 {
01132 case 0 :
01133 {
01134
01135
01136
01137
01138
01139 if (*pin >= 0)
01140 {
01141 ::close(pin[WR]);
01142 ::dup2(pin[RD], STDIN_FILENO);
01143 ::close(pin[RD]);
01144 }
01145 if (*pout >= 0)
01146 {
01147 ::close(pout[RD]);
01148 ::dup2(pout[WR], STDOUT_FILENO);
01149 ::close(pout[WR]);
01150 }
01151 if (*perr >= 0)
01152 {
01153 ::close(perr[RD]);
01154 ::dup2(perr[WR], STDERR_FILENO);
01155 ::close(perr[WR]);
01156 }
01157 break;
01158 }
01159 case -1 :
01160 {
01161
01162 error_ = errno;
01163
01164 close_fd_array(fd, 6);
01165 break;
01166 }
01167 default :
01168 {
01169
01170 ppid_ = pid;
01171
01172
01173 if (*pin >= 0)
01174 {
01175 wpipe_ = pin[WR];
01176 ::close(pin[RD]);
01177 }
01178 if (*pout >= 0)
01179 {
01180 rpipe_[rsrc_out] = pout[RD];
01181 ::close(pout[WR]);
01182 }
01183 if (*perr >= 0)
01184 {
01185 rpipe_[rsrc_err] = perr[RD];
01186 ::close(perr[WR]);
01187 }
01188
01189 if (rpipe_[rsrc_out] == -1 && rpipe_[rsrc_err] >= 0)
01190 {
01191
01192 read_err(true);
01193 }
01194 }
01195 }
01196 }
01197 else
01198 {
01199
01200 close_fd_array(fd, 6);
01201 }
01202 return pid;
01203 }
01204
01214 template <typename C, typename T>
01215 basic_pstreambuf<C,T>*
01216 basic_pstreambuf<C,T>::close()
01217 {
01218 basic_pstreambuf<C,T>* ret = NULL;
01219 if (is_open())
01220 {
01221 sync();
01222
01223 destroy_buffers(pstdin|pstdout|pstderr);
01224
01225
01226 close_fd_array(&wpipe_, 1);
01227 close_fd_array(rpipe_, 2);
01228
01229 if (wait() == 1)
01230 {
01231 ret = this;
01232 }
01233 }
01234 return ret;
01235 }
01236
01240 template <typename C, typename T>
01241 inline void
01242 basic_pstreambuf<C,T>::init_rbuffers()
01243 {
01244 rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
01245 rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
01246 rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
01247 }
01248
01249 template <typename C, typename T>
01250 void
01251 basic_pstreambuf<C,T>::create_buffers(pmode mode)
01252 {
01253 if (mode & pstdin)
01254 {
01255 delete[] wbuffer_;
01256 wbuffer_ = new char_type[bufsz];
01257 this->setp(wbuffer_, wbuffer_ + bufsz);
01258 }
01259 if (mode & pstdout)
01260 {
01261 delete[] rbuffer_[rsrc_out];
01262 rbuffer_[rsrc_out] = new char_type[bufsz];
01263 if (rsrc_ == rsrc_out)
01264 this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
01265 rbuffer_[rsrc_out] + pbsz);
01266 }
01267 if (mode & pstderr)
01268 {
01269 delete[] rbuffer_[rsrc_err];
01270 rbuffer_[rsrc_err] = new char_type[bufsz];
01271 if (rsrc_ == rsrc_err)
01272 this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
01273 rbuffer_[rsrc_err] + pbsz);
01274 }
01275 }
01276
01277 template <typename C, typename T>
01278 void
01279 basic_pstreambuf<C,T>::destroy_buffers(pmode mode)
01280 {
01281 if (mode & pstdin)
01282 {
01283 this->setp(NULL, NULL);
01284 delete[] wbuffer_;
01285 wbuffer_ = NULL;
01286 }
01287 if (mode & pstdout)
01288 {
01289 if (rsrc_ == rsrc_out)
01290 this->setg(NULL, NULL, NULL);
01291 delete[] rbuffer_[rsrc_out];
01292 rbuffer_[rsrc_out] = NULL;
01293 }
01294 if (mode & pstderr)
01295 {
01296 if (rsrc_ == rsrc_err)
01297 this->setg(NULL, NULL, NULL);
01298 delete[] rbuffer_[rsrc_err];
01299 rbuffer_[rsrc_err] = NULL;
01300 }
01301 }
01302
01303 template <typename C, typename T>
01304 typename basic_pstreambuf<C,T>::buf_read_src
01305 basic_pstreambuf<C,T>::switch_read_buffer(buf_read_src src)
01306 {
01307 if (rsrc_ != src)
01308 {
01309 char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
01310 this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
01311 for (std::size_t i = 0; i < 3; ++i)
01312 rbufstate_[i] = tmpbufstate[i];
01313 rsrc_ = src;
01314 }
01315 return rsrc_;
01316 }
01317
01330 template <typename C, typename T>
01331 int
01332 basic_pstreambuf<C,T>::wait(bool nohang)
01333 {
01334 int exited = -1;
01335 if (is_open())
01336 {
01337 int status;
01338 switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0))
01339 {
01340 case 0 :
01341
01342 exited = 0;
01343 break;
01344 case -1 :
01345 error_ = errno;
01346 break;
01347 default :
01348
01349 ppid_ = 0;
01350 status_ = status;
01351 exited = 1;
01352 destroy_buffers(pstdin|pstdout|pstderr);
01353 close_fd_array(&wpipe_, 1);
01354 close_fd_array(rpipe_, 2);
01355 break;
01356 }
01357 }
01358 return exited;
01359 }
01360
01371 template <typename C, typename T>
01372 inline basic_pstreambuf<C,T>*
01373 basic_pstreambuf<C,T>::kill(int signal)
01374 {
01375 basic_pstreambuf<C,T>* ret = NULL;
01376 if (is_open())
01377 {
01378 if (::kill(ppid_, signal))
01379 error_ = errno;
01380 else
01381 {
01382
01383 ret = this;
01384 }
01385 }
01386 return ret;
01387 }
01388
01393 template <typename C, typename T>
01394 inline bool
01395 basic_pstreambuf<C,T>::exited()
01396 {
01397 return ppid_ == 0 || wait(true)==1;
01398 }
01399
01400
01406 template <typename C, typename T>
01407 inline int
01408 basic_pstreambuf<C,T>::status() const
01409 {
01410 return status_;
01411 }
01412
01416 template <typename C, typename T>
01417 inline int
01418 basic_pstreambuf<C,T>::error() const
01419 {
01420 return error_;
01421 }
01422
01427 template <typename C, typename T>
01428 inline void
01429 basic_pstreambuf<C,T>::peof()
01430 {
01431 sync();
01432 destroy_buffers(pstdin);
01433 close_fd_array(&wpipe_, 1);
01434 }
01435
01446 template <typename C, typename T>
01447 inline bool
01448 basic_pstreambuf<C,T>::is_open() const
01449 {
01450 return ppid_ > 0;
01451 }
01452
01461 template <typename C, typename T>
01462 inline bool
01463 basic_pstreambuf<C,T>::read_err(bool readerr)
01464 {
01465 buf_read_src src = readerr ? rsrc_err : rsrc_out;
01466 if (rpipe_[src]>=0)
01467 {
01468 switch_read_buffer(src);
01469 return true;
01470 }
01471 return false;
01472 }
01473
01484 template <typename C, typename T>
01485 typename basic_pstreambuf<C,T>::int_type
01486 basic_pstreambuf<C,T>::overflow(int_type c)
01487 {
01488 if (!empty_buffer())
01489 return traits_type::eof();
01490 else if (!traits_type::eq_int_type(c, traits_type::eof()))
01491 return this->sputc(c);
01492 else
01493 return traits_type::not_eof(c);
01494 }
01495
01496
01497 template <typename C, typename T>
01498 int
01499 basic_pstreambuf<C,T>::sync()
01500 {
01501 return !exited() && empty_buffer() ? 0 : -1;
01502 }
01503
01509 template <typename C, typename T>
01510 std::streamsize
01511 basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
01512 {
01513 if (n < this->epptr() - this->pptr())
01514 {
01515 std::memcpy(this->pptr(), s, n * sizeof(char_type));
01516 this->pbump(n);
01517 return n;
01518 }
01519 else
01520 {
01521 for (std::streamsize i = 0; i < n; ++i)
01522 {
01523 if (traits_type::eq_int_type(this->sputc(s[i]), traits_type::eof()))
01524 return i;
01525 }
01526 return n;
01527 }
01528 }
01529
01533 template <typename C, typename T>
01534 bool
01535 basic_pstreambuf<C,T>::empty_buffer()
01536 {
01537 const std::streamsize count = this->pptr() - this->pbase();
01538 const std::streamsize written = this->write(this->wbuffer_, count);
01539 if (count > 0 && written == count)
01540 {
01541 this->pbump(-written);
01542 return true;
01543 }
01544 return false;
01545 }
01546
01555 template <typename C, typename T>
01556 typename basic_pstreambuf<C,T>::int_type
01557 basic_pstreambuf<C,T>::underflow()
01558 {
01559 if (this->gptr() < this->egptr() || fill_buffer())
01560 return traits_type::to_int_type(*this->gptr());
01561 else
01562 return traits_type::eof();
01563 }
01564
01573 template <typename C, typename T>
01574 typename basic_pstreambuf<C,T>::int_type
01575 basic_pstreambuf<C,T>::pbackfail(int_type c)
01576 {
01577 if (this->gptr() != this->eback())
01578 {
01579 this->gbump(-1);
01580 if (!traits_type::eq_int_type(c, traits_type::eof()))
01581 *this->gptr() = traits_type::to_char_type(c);
01582 return traits_type::not_eof(c);
01583 }
01584 else
01585 return traits_type::eof();
01586 }
01587
01591 template <typename C, typename T>
01592 bool
01593 basic_pstreambuf<C,T>::fill_buffer()
01594 {
01595 const std::streamsize pb1 = this->gptr() - this->eback();
01596 const std::streamsize pb2 = pbsz;
01597 const std::streamsize npb = std::min(pb1, pb2);
01598
01599 std::memmove( rbuffer() + pbsz - npb,
01600 this->gptr() - npb,
01601 npb * sizeof(char_type) );
01602
01603 const std::streamsize rc = read(rbuffer() + pbsz, bufsz - pbsz);
01604
01605 if (rc > 0)
01606 {
01607 this->setg( rbuffer() + pbsz - npb,
01608 rbuffer() + pbsz,
01609 rbuffer() + pbsz + rc );
01610 return true;
01611 }
01612 else
01613 {
01614 this->setg(NULL, NULL, NULL);
01615 return false;
01616 }
01617 }
01618
01628 template <typename C, typename T>
01629 inline std::streamsize
01630 basic_pstreambuf<C,T>::write(char_type* s, std::streamsize n)
01631 {
01632 return wpipe() >= 0 ? ::write(wpipe(), s, n * sizeof(char_type)) : 0;
01633 }
01634
01644 template <typename C, typename T>
01645 inline std::streamsize
01646 basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
01647 {
01648 return rpipe() >= 0 ? ::read(rpipe(), s, n * sizeof(char_type)) : 0;
01649 }
01650
01652 template <typename C, typename T>
01653 inline typename basic_pstreambuf<C,T>::fd_type&
01654 basic_pstreambuf<C,T>::wpipe()
01655 {
01656 return wpipe_;
01657 }
01658
01660 template <typename C, typename T>
01661 inline typename basic_pstreambuf<C,T>::fd_type&
01662 basic_pstreambuf<C,T>::rpipe()
01663 {
01664 return rpipe_[rsrc_];
01665 }
01666
01668 template <typename C, typename T>
01669 inline typename basic_pstreambuf<C,T>::fd_type&
01670 basic_pstreambuf<C,T>::rpipe(buf_read_src which)
01671 {
01672 return rpipe_[which];
01673 }
01674
01676 template <typename C, typename T>
01677 inline typename basic_pstreambuf<C,T>::char_type*
01678 basic_pstreambuf<C,T>::rbuffer()
01679 {
01680 return rbuffer_[rsrc_];
01681 }
01682
01683
01684
01685
01686
01687
01697 template <typename C, typename T>
01698 inline
01699 pstream_common<C,T>::pstream_common()
01700 : std::basic_ios<C,T>(NULL)
01701 , command_()
01702 , buf_()
01703 {
01704 this->init(&buf_);
01705 }
01706
01715 template <typename C, typename T>
01716 inline
01717 pstream_common<C,T>::pstream_common(const std::string& command, pmode mode)
01718 : std::basic_ios<C,T>(NULL)
01719 , command_(command)
01720 , buf_()
01721 {
01722 this->init(&buf_);
01723 do_open(command, mode);
01724 }
01725
01735 template <typename C, typename T>
01736 inline
01737 pstream_common<C,T>::pstream_common( const std::string& file,
01738 const argv_type& argv,
01739 pmode mode )
01740 : std::basic_ios<C,T>(NULL)
01741 , command_(file)
01742 , buf_()
01743 {
01744 this->init(&buf_);
01745 do_open(file, argv, mode);
01746 }
01747
01757 template <typename C, typename T>
01758 inline
01759 pstream_common<C,T>::~pstream_common()
01760 {
01761 }
01762
01771 template <typename C, typename T>
01772 inline void
01773 pstream_common<C,T>::do_open(const std::string& command, pmode mode)
01774 {
01775 if (!buf_.open((command_=command), mode))
01776 this->setstate(std::ios_base::failbit);
01777 }
01778
01788 template <typename C, typename T>
01789 inline void
01790 pstream_common<C,T>::do_open( const std::string& file,
01791 const argv_type& argv,
01792 pmode mode )
01793 {
01794 if (!buf_.open((command_=file), argv, mode))
01795 this->setstate(std::ios_base::failbit);
01796 }
01797
01799 template <typename C, typename T>
01800 inline void
01801 pstream_common<C,T>::close()
01802 {
01803 if (!buf_.close())
01804 this->setstate(std::ios_base::failbit);
01805 }
01806
01811 template <typename C, typename T>
01812 inline bool
01813 pstream_common<C,T>::is_open() const
01814 {
01815 return buf_.is_open();
01816 }
01817
01819 template <typename C, typename T>
01820 inline const std::string&
01821 pstream_common<C,T>::command() const
01822 {
01823 return command_;
01824 }
01825
01827
01828 template <typename C, typename T>
01829 inline typename pstream_common<C,T>::streambuf_type*
01830 pstream_common<C,T>::rdbuf() const
01831 {
01832 return const_cast<streambuf_type*>(&buf_);
01833 }
01834
01835
01836 #if REDI_EVISCERATE_PSTREAMS
01837
01866 template <typename C, typename T>
01867 std::size_t
01868 basic_pstreambuf<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
01869 {
01870 in = out = err = NULL;
01871 std::size_t open_files = 0;
01872 if (wpipe() > -1)
01873 {
01874 if ((in = ::fdopen(wpipe(), "w")))
01875 {
01876 open_files |= pstdin;
01877 }
01878 }
01879 if (rpipe(rsrc_out) > -1)
01880 {
01881 if ((out = ::fdopen(rpipe(rsrc_out), "r")))
01882 {
01883 open_files |= pstdout;
01884 }
01885 }
01886 if (rpipe(rsrc_err) > -1)
01887 {
01888 if ((err = ::fdopen(rpipe(rsrc_err), "r")))
01889 {
01890 open_files |= pstderr;
01891 }
01892 }
01893 return open_files;
01894 }
01895
01906 template <typename C, typename T>
01907 inline std::size_t
01908 pstream_common<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
01909 {
01910 return buf_.fopen(in, out, err);
01911 }
01912
01913 #endif // REDI_EVISCERATE_PSTREAMS
01914
01915
01916 }
01917
01923 #endif // REDI_PSTREAM_H_SEEN
01924
01925
01926