00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00033 #ifndef REDI_PSTREAM_H_SEEN
00034 #define REDI_PSTREAM_H_SEEN
00035
00036 #if defined(__GNUC__) && (__GNUC__ < 3)
00037
00039 #define PSTREAMS_VERSION 0x0011 // 0.17
00040
00041
00042
00043 #if ! defined(REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE)
00044 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
00045 # define REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE 1
00046 #elif defined(__NetBSD_Version__) && __NetBSD_Version__ >= 0x01040000
00047 # define REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE 1
00048 #endif
00049 #endif
00050
00051
00052 #include <iostream>
00053 #include <istream.h>
00054 #include <ostream.h>
00055 #include <string>
00056 #include <cstdio>
00057 #include <cerrno>
00058
00059
00060
00061
00062
00063
00064
00065 namespace std {
00066 template<typename _CharT>
00067 class char_traits : public string_char_traits<_CharT>
00068 {
00069 public:
00070 typedef _CharT char_type;
00071
00072 typedef int int_type;
00073 typedef streampos pos_type;
00074 typedef streamoff off_type;
00075
00076 static char_type to_char_type(const int_type& __c) { return char_type(__c); }
00077
00078 static int_type to_int_type(const char_type& __c) { return int_type(__c); }
00079
00080 static bool eq_int_type(const int_type& __c1, const int_type& __c2)
00081 { return __c1 == __c2; }
00082
00083 static int_type eof() { return static_cast<int_type>(EOF); }
00084
00085 static int_type not_eof(const int_type& __c)
00086 { return (__c == eof()) ? 0 : __c; }
00087 };
00088 template<typename _CharT, typename _Traits>
00089 class basic_streambuf : public streambuf
00090 { };
00091 template<typename _CharT, typename _Traits>
00092 class basic_ios : public ios
00093 {
00094 public:
00095 basic_ios(streambuf* sb = 0, ostream* tie_to = 0) : ios(sb, tie_to) { }
00096 };
00097 template<typename _CharT, typename _Traits>
00098 class basic_istream : public istream
00099 {
00100 public:
00101 basic_istream() : istream() { }
00102 basic_istream(streambuf* sb, ostream*tied=NULL) : istream(sb, tied) { }
00103 };
00104 template<typename _CharT, typename _Traits>
00105 class basic_ostream : public ostream
00106 { };
00107 template<typename _CharT, typename _Traits>
00108 class basic_iostream : public iostream
00109 { };
00110 }
00111
00112 namespace IXE {
00125 namespace io
00126 {
00128 std::string
00129 openmode2str(std::ios::openmode mode);
00130
00131
00133 template <typename CharT, typename Traits>
00134 class basic_pstreambuf : public std::basic_streambuf<CharT, Traits>
00135 {
00136 public:
00137
00138 typedef CharT char_type;
00139 typedef Traits traits_type;
00140 typedef typename traits_type::int_type int_type;
00141 typedef typename traits_type::off_type off_type;
00142 typedef typename traits_type::pos_type pos_type;
00143
00145 basic_pstreambuf();
00146
00148 basic_pstreambuf(const std::string& command, std::ios::openmode mode);
00149
00151 ~basic_pstreambuf();
00152
00154 basic_pstreambuf*
00155 open(const std::string& command, std::ios::openmode mode);
00156
00158 basic_pstreambuf*
00159 close();
00160
00162 bool
00163 is_open() const;
00164
00165 protected:
00167 int_type
00168 overflow(int_type c);
00169
00171 int_type
00172 uflow();
00173
00175 int_type
00176 underflow();
00177
00179 int_type
00180 pbackfail(int_type c = traits_type::eof());
00181
00182 std::streamsize
00183 write(char_type* s, std::streamsize n);
00184
00185 std::streamsize
00186 read(char_type* s, std::streamsize n);
00187
00189 bool
00190 write(char_type c);
00191
00193 bool
00194 read(char_type& c);
00195
00196 private:
00197 basic_pstreambuf(const basic_pstreambuf&);
00198 basic_pstreambuf& operator=(const basic_pstreambuf&);
00199
00200 FILE* file_;
00201 char_type char_buf_;
00202 bool take_from_buf_;
00203 };
00204
00205
00207 template <typename CharT, typename Traits = std::char_traits<CharT> >
00208 class basic_ipstream : public std::basic_istream<CharT, Traits>
00209 {
00210 typedef std::basic_istream<CharT, Traits> istream_type;
00211 typedef basic_pstreambuf<CharT, Traits> streambuf_type;
00212
00213 public:
00215 basic_ipstream();
00216
00218 basic_ipstream(const std::string& command, std::ios::openmode mode = ios::in);
00219
00221 ~basic_ipstream() { }
00222
00224 void
00225 open(const std::string& command, std::ios::openmode mode = std::ios::in);
00226
00228 void
00229 close();
00230
00232 bool
00233 is_open() const;
00234
00236 const std::string&
00237 command() const;
00238
00239 private:
00240 std::string command_;
00241 streambuf_type buf_;
00242 };
00243
00244
00246 template <typename CharT, typename Traits = std::char_traits<CharT> >
00247 class basic_opstream : public std::basic_ostream<CharT, Traits>
00248 {
00249 typedef std::basic_ostream<CharT, Traits> ostream_type;
00250 typedef basic_pstreambuf<CharT, Traits> streambuf_type;
00251
00252 public:
00254 basic_opstream();
00255
00257 basic_opstream(const std::string& command, std::ios::openmode mode = std::ios::out);
00258
00260 ~basic_opstream() { }
00261
00263 void
00264 open(const std::string& command, std::ios::openmode mode = std::ios::out);
00265
00267 void
00268 close();
00269
00271 bool
00272 is_open() const;
00273
00275 const std::string&
00276 command() const;
00277
00278 private:
00279 std::string command_;
00280 streambuf_type buf_;
00281 };
00282
00284 typedef basic_ipstream<char> ipstream;
00286 typedef basic_opstream<char> opstream;
00287
00288
00289
00290
00297 template <typename C, typename T>
00298 inline
00299 basic_pstreambuf<C,T>::basic_pstreambuf()
00300 : file_(0)
00301 , take_from_buf_(false)
00302 { }
00303
00312 template <typename C, typename T>
00313 inline
00314 basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& command, std::ios::openmode mode )
00315 : file_(0)
00316 , take_from_buf_(false)
00317 {
00318 this->open(command, mode);
00319 }
00320
00325 template <typename C, typename T>
00326 inline
00327 basic_pstreambuf<C,T>::~basic_pstreambuf()
00328 {
00329 this->close();
00330 }
00331
00344 template <typename C, typename T>
00345 inline basic_pstreambuf<C,T>*
00346 basic_pstreambuf<C,T>::open( const std::string& command, std::ios::openmode mode )
00347 {
00348 basic_pstreambuf<C,T>* ret = NULL;
00349 if (!this->is_open())
00350 {
00351 file_ = ::popen(command.c_str(), openmode2str(mode).c_str());
00352 if (this->is_open())
00353 ret = this;
00354 }
00355 return ret;
00356 }
00357
00362 template <typename C, typename T>
00363 inline basic_pstreambuf<C,T>*
00364 basic_pstreambuf<C,T>::close()
00365 {
00366 basic_pstreambuf<C,T>* ret = NULL;
00367 if (this->is_open())
00368 {
00369 errno = 0;
00370 ::pclose(file_);
00371 if (errno==0)
00372 {
00373 ret = this;
00374 file_ = 0;
00375 }
00376 }
00377 return ret;
00378 }
00379
00387 template <typename C, typename T>
00388 inline bool
00389 basic_pstreambuf<C,T>::is_open() const
00390 {
00391 return bool(file_);
00392 }
00393
00394
00405 template <typename C, typename T>
00406 typename basic_pstreambuf<C,T>::int_type
00407 basic_pstreambuf<C,T>::overflow(int_type c)
00408 {
00409 if (!traits_type::eq_int_type(c, traits_type::eof()))
00410 {
00411 if (!this->write(traits_type::to_char_type(c)))
00412 return traits_type::eof();
00413 else
00414 return c;
00415 }
00416 return traits_type::not_eof(c);
00417 }
00418
00429 template <typename C, typename T>
00430 typename basic_pstreambuf<C,T>::int_type
00431 basic_pstreambuf<C,T>::uflow()
00432 {
00433 if (take_from_buf_)
00434 {
00435 take_from_buf_ = false;
00436 return traits_type::to_int_type(char_buf_);
00437 }
00438 else
00439 {
00440 char_type c;
00441
00442 if (!this->read(c))
00443 {
00444 return traits_type::eof();
00445 }
00446 else
00447 {
00448 char_buf_ = c;
00449 return traits_type::to_int_type(c);
00450 }
00451 }
00452 }
00453
00463 template <typename C, typename T>
00464 typename basic_pstreambuf<C,T>::int_type
00465 basic_pstreambuf<C,T>::underflow()
00466 {
00467 if (take_from_buf_)
00468 {
00469 return traits_type::to_int_type(char_buf_);
00470 }
00471 else
00472 {
00473 char_type c;
00474
00475 if (!this->read(c))
00476 {
00477 return traits_type::eof();
00478 }
00479 else
00480 {
00481 take_from_buf_ = true;
00482 char_buf_ = c;
00483 return traits_type::to_int_type(c);
00484 }
00485 }
00486 }
00487
00497 template <typename C, typename T>
00498 typename basic_pstreambuf<C,T>::int_type
00499 basic_pstreambuf<C,T>::pbackfail(int_type c)
00500 {
00501 if (!take_from_buf_)
00502 {
00503 if (!traits_type::eq_int_type(c, traits_type::eof()))
00504 {
00505 char_buf_ = traits_type::to_char_type(c);
00506 }
00507 take_from_buf_ = true;
00508 return traits_type::to_int_type(char_buf_);
00509 }
00510 else
00511 {
00512 return traits_type::eof();
00513 }
00514 }
00515
00522 template <typename C, typename T>
00523 inline bool
00524 basic_pstreambuf<C,T>::write(char_type c)
00525 {
00526 return (this->write(&c, 1) == 1);
00527 }
00528
00536 template <typename C, typename T>
00537 inline bool
00538 basic_pstreambuf<C,T>::read(char_type& c)
00539 {
00540 return (this->read(&c, 1) == 1);
00541 }
00542
00550 template <typename C, typename T>
00551 inline std::streamsize
00552 basic_pstreambuf<C,T>::write(char_type* s, std::streamsize n)
00553 {
00554 return (file_ ? std::fwrite(s, sizeof(char_type), n, file_) : 0);
00555 }
00556
00564 template <typename C, typename T>
00565 inline std::streamsize
00566 basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
00567 {
00568 return (file_ ? std::fread(s, sizeof(char_type), n, file_) : 0);
00569 }
00570
00571
00572
00573
00582 template <typename C, typename T>
00583 inline
00584 basic_ipstream<C,T>::basic_ipstream()
00585 : istream_type(NULL)
00586 , command_()
00587 , buf_()
00588 {
00589 this->init(&buf_);
00590 }
00591
00600 template <typename C, typename T>
00601 inline
00602 basic_ipstream<C,T>::basic_ipstream( const std::string& command, std::ios::openmode mode )
00603 : istream_type(NULL)
00604 , command_(command)
00605 , buf_()
00606 {
00607 this->init(&buf_);
00608 this->open(command_, mode);
00609 }
00610
00619 template <typename C, typename T>
00620 inline void
00621 basic_ipstream<C,T>::open( const std::string& command, std::ios::openmode mode )
00622 {
00623 if (!buf_.open((command_=command), (mode|std::ios::in)))
00624 this->setstate(std::ios::failbit);
00625 }
00626
00628 template <typename C, typename T>
00629 inline void
00630 basic_ipstream<C,T>::close()
00631 {
00632 if (!buf_.close())
00633 this->setstate(std::ios::failbit);
00634 }
00635
00640 template <typename C, typename T>
00641 inline bool
00642 basic_ipstream<C,T>::is_open() const
00643 {
00644 return buf_.is_open();
00645 }
00646
00648 template <typename C, typename T>
00649 inline const std::string&
00650 basic_ipstream<C,T>::command() const
00651 {
00652 return command_;
00653 }
00654
00655
00656
00657
00667 template <typename C, typename T>
00668 inline
00669 basic_opstream<C,T>::basic_opstream()
00670 : ostream_type(NULL)
00671 , command_()
00672 , buf_()
00673 {
00674 this->init(&buf_);
00675 }
00676
00685 template <typename C, typename T>
00686 inline
00687 basic_opstream<C,T>::basic_opstream( const std::string& command, std::ios::openmode mode )
00688 : ostream_type(NULL)
00689 , command_(command)
00690 , buf_()
00691 {
00692 this->init(&buf_);
00693 this->open(command_, mode);
00694 }
00695
00704 template <typename C, typename T>
00705 inline void
00706 basic_opstream<C,T>::open( const std::string& command, std::ios::openmode mode )
00707 {
00708 if (!buf_.open((command_=command), (mode|std::ios::out)))
00709 this->setstate(std::ios::failbit);
00710 }
00711
00713 template <typename C, typename T>
00714 inline void
00715 basic_opstream<C,T>::close()
00716 {
00717 if (!buf_.close())
00718 this->setstate(std::ios::failbit);
00719 }
00720
00725 template <typename C, typename T>
00726 inline bool
00727 basic_opstream<C,T>::is_open() const
00728 {
00729 return buf_.is_open();
00730 }
00731
00733 template <typename C, typename T>
00734 inline const std::string&
00735 basic_opstream<C,T>::command() const
00736 {
00737 return command_;
00738 }
00739
00740
00741
00742
00750 inline std::string
00751 openmode2str( std::ios::openmode mode )
00752 {
00753 using std::ios;
00754
00755 mode &= (ios::in|ios::out);
00756 if (mode == ios::in)
00757 return "r";
00758 else if (mode == ios::out)
00759 return "w";
00760 else if (mode == (ios::in|ios::out))
00761 return "r+";
00762 else
00763 return "";
00764 }
00765
00766 #if REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE
00767
00769 template <typename CharT, typename Traits = std::char_traits<CharT> >
00770 class basic_pstream : public std::basic_iostream<CharT, Traits>
00771 {
00772 typedef std::basic_iostream<CharT, Traits> iostream_type;
00773 typedef basic_pstreambuf<CharT, Traits> streambuf_type;
00774
00775 public:
00777 basic_pstream();
00778
00780 basic_pstream(const std::string& command, std::ios::openmode mode = std::ios::in|std::ios::out);
00781
00783 ~basic_pstream() { }
00784
00786 void
00787 open(const std::string& command, std::ios::openmode mode = std::ios::in|std::ios::out);
00788
00790 void
00791 close();
00792
00794 bool
00795 is_open() const;
00796
00798 const std::string&
00799 command() const;
00800
00801 private:
00802 std::string command_;
00803 streambuf_type buf_;
00804 };
00805
00807 typedef basic_pstream<char> pstream;
00808
00809
00810
00811
00822 template <typename C, typename T>
00823 basic_pstream<C,T>::basic_pstream()
00824 : iostream_type(NULL)
00825 , command_()
00826 , buf_()
00827 {
00828 this->init(&buf_);
00829 }
00830
00838 template <typename C, typename T>
00839 basic_pstream<C,T>::basic_pstream(const std::string& command, std::ios::openmode mode)
00840 : iostream_type(NULL)
00841 , command_(command)
00842 , buf_()
00843 {
00844 this->init(&buf_);
00845 this->open(command_, mode);
00846 }
00847
00855 template <typename C, typename T>
00856 inline void
00857 basic_pstream<C,T>::open(const std::string& command, std::ios::openmode mode)
00858 {
00859 if (!buf_.open((command_=command), mode))
00860 this->setstate(std::ios::failbit);
00861 }
00862
00864 template <typename C, typename T>
00865 inline void
00866 basic_pstream<C,T>::close()
00867 {
00868 if (!buf_.close())
00869 this->setstate(std::ios::failbit);
00870 }
00871
00876 template <typename C, typename T>
00877 inline bool
00878 basic_pstream<C,T>::is_open() const
00879 {
00880 return buf_.is_open();
00881 }
00882
00884 template <typename C, typename T>
00885 inline const std::string&
00886 basic_pstream<C,T>::command() const
00887 {
00888 return command_;
00889 }
00890
00891 #endif // REDI_PSTREAMS_POPEN_USES_BIDIRECTIONAL_PIPE
00892
00893 }
00894 }
00895
00896
00897 #else // !defined(__GNUC__) || (__GNUC__ >= 3)
00898
00899 #include <ios>
00900 #include <streambuf>
00901 #include <istream>
00902 #include <ostream>
00903 #include <string>
00904 #include <vector>
00905 #include <algorithm>
00906 #include <cstring>
00907 #include <cerrno>
00908 #include <cstddef>
00909 #include <cstdlib>
00910 #include <sys/types.h>
00911 #include <sys/wait.h>
00912 #include <unistd.h>
00913 #include <signal.h>
00914 #if REDI_EVISCERATE_PSTREAMS
00915 #include <stdio.h>
00916 #endif
00917
00918
00920 #define PSTREAMS_VERSION 0x0050 // 0.5.0
00921
00922 namespace IXE {
00935 namespace io
00936 {
00938 struct pstreams
00939 {
00941 typedef std::ios::openmode pmode;
00942
00944 typedef std::vector<std::string> argv_type;
00945
00946 static const pmode pstdin = std::ios::out;
00947 static const pmode pstdout = std::ios::in;
00948 static const pmode pstderr = std::ios::app;
00949
00950 protected:
00951 enum { bufsz = 32 };
00952 enum { pbsz = 2 };
00953 };
00954
00956 template <typename CharT, typename Traits = std::char_traits<CharT> >
00957 class basic_pstreambuf
00958 : public std::basic_streambuf<CharT, Traits>
00959 , public pstreams
00960 {
00961 public:
00962
00963 typedef CharT char_type;
00964 typedef Traits traits_type;
00965 typedef typename traits_type::int_type int_type;
00966 typedef typename traits_type::off_type off_type;
00967 typedef typename traits_type::pos_type pos_type;
00969 typedef int fd_type;
00971 typedef fd_type fd_t;
00972
00974 basic_pstreambuf();
00975
00977 basic_pstreambuf(const std::string& command, pmode mode);
00978
00980 basic_pstreambuf( const std::string& file,
00981 const argv_type& argv,
00982 pmode mode );
00983
00985 ~basic_pstreambuf();
00986
00988 basic_pstreambuf*
00989 open(const std::string& command, pmode mode);
00990
00992 basic_pstreambuf*
00993 open(const std::string& file, const argv_type& argv, pmode mode);
00994
00996 basic_pstreambuf*
00997 close();
00998
01000 basic_pstreambuf*
01001 kill(int signal = SIGTERM);
01002
01004 void
01005 peof();
01006
01008 bool
01009 read_err(bool readerr = true);
01010
01012 bool
01013 is_open() const;
01014
01016 bool
01017 exited();
01018
01019 #if REDI_EVISCERATE_PSTREAMS
01021 std::size_t
01022 fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
01023 #endif
01024
01026 int
01027 status() const;
01028
01030 int
01031 error() const;
01032
01033 protected:
01035 int_type
01036 overflow(int_type c);
01037
01039 int_type
01040 underflow();
01041
01043 int_type
01044 pbackfail(int_type c = traits_type::eof());
01045
01047 int
01048 sync();
01049
01051 std::streamsize
01052 xsputn(const char_type* s, std::streamsize n);
01053
01055 std::streamsize
01056 write(char_type* s, std::streamsize n);
01057
01059 std::streamsize
01060 read(char_type* s, std::streamsize n);
01061
01062 protected:
01064 enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
01065
01067 pid_t
01068 fork(pmode mode);
01069
01071 int
01072 wait(bool nohang = false);
01073
01075 fd_type&
01076 wpipe();
01077
01079 fd_type&
01080 rpipe();
01081
01083 fd_type&
01084 rpipe(buf_read_src which);
01085
01086 void
01087 create_buffers(pmode mode);
01088
01089 void
01090 destroy_buffers(pmode mode);
01091
01093 bool
01094 empty_buffer();
01095
01096 bool
01097 fill_buffer();
01098
01100 char_type*
01101 rbuffer();
01102
01103 buf_read_src
01104 switch_read_buffer(buf_read_src);
01105
01106 private:
01107 basic_pstreambuf(const basic_pstreambuf&);
01108 basic_pstreambuf& operator=(const basic_pstreambuf&);
01109
01110 void
01111 init_rbuffers();
01112
01113 pid_t ppid_;
01114 fd_type wpipe_;
01115 fd_type rpipe_[2];
01116 char_type* wbuffer_;
01117 char_type* rbuffer_[2];
01118 char_type* rbufstate_[3];
01120 buf_read_src rsrc_;
01121 int status_;
01122 int error_;
01123 };
01124
01126 template <typename CharT, typename Traits = std::char_traits<CharT> >
01127 class pstream_common
01128 : virtual public std::basic_ios<CharT, Traits>
01129 , virtual public pstreams
01130 {
01131 protected:
01132 typedef basic_pstreambuf<CharT, Traits> streambuf_type;
01133
01135 pstream_common();
01136
01138 pstream_common(const std::string& command, pmode mode);
01139
01141 pstream_common( const std::string& file,
01142 const argv_type& argv,
01143 pmode mode );
01144
01146 virtual
01147 ~pstream_common() = 0;
01148
01150 void
01151 do_open(const std::string& command, pmode mode);
01152
01154 void
01155 do_open(const std::string& file, const argv_type& argv, pmode mode);
01156
01157 public:
01159 void
01160 close();
01161
01163 bool
01164 is_open() const;
01165
01167 const std::string&
01168 command() const;
01169
01171 streambuf_type*
01172 rdbuf() const;
01173
01174 #if REDI_EVISCERATE_PSTREAMS
01176 std::size_t
01177 fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
01178 #endif
01179
01180 protected:
01181 std::string command_;
01182 streambuf_type buf_;
01183 };
01184
01185
01198 template <typename CharT, typename Traits = std::char_traits<CharT> >
01199 class basic_ipstream
01200 : public std::basic_istream<CharT, Traits>
01201 , public pstream_common<CharT, Traits>
01202 , virtual public pstreams
01203 {
01204 typedef std::basic_istream<CharT, Traits> istream_type;
01205 typedef pstream_common<CharT, Traits> pbase_type;
01206
01207 using pbase_type::buf_;
01208
01209 public:
01211 typedef typename pbase_type::pmode pmode;
01212
01214 typedef typename pbase_type::argv_type argv_type;
01215
01217 basic_ipstream()
01218 : istream_type(NULL), pbase_type()
01219 { }
01220
01231 basic_ipstream(const std::string& command, pmode mode = pstdout)
01232 : istream_type(NULL), pbase_type(command, mode|pstdout)
01233 { }
01234
01246 basic_ipstream( const std::string& file,
01247 const argv_type& argv,
01248 pmode mode = pstdout )
01249 : istream_type(NULL), pbase_type(file, argv, mode|pstdout)
01250 { }
01251
01257 ~basic_ipstream()
01258 { }
01259
01270 void
01271 open(const std::string& command, pmode mode = pstdout)
01272 {
01273 this->do_open(command, mode|pstdout);
01274 }
01275
01287 void
01288 open( const std::string& file,
01289 const argv_type& argv,
01290 pmode mode = pstdout )
01291 {
01292 this->do_open(file, argv, mode|pstdout);
01293 }
01294
01299 basic_ipstream&
01300 out()
01301 {
01302 this->buf_.read_err(false);
01303 return *this;
01304 }
01305
01310 basic_ipstream&
01311 err()
01312 {
01313 this->buf_.read_err(true);
01314 return *this;
01315 }
01316 };
01317
01318
01330 template <typename CharT, typename Traits = std::char_traits<CharT> >
01331 class basic_opstream
01332 : public std::basic_ostream<CharT, Traits>
01333 , public pstream_common<CharT, Traits>
01334 , virtual public pstreams
01335 {
01336 typedef std::basic_ostream<CharT, Traits> ostream_type;
01337 typedef pstream_common<CharT, Traits> pbase_type;
01338
01339 using pbase_type::buf_;
01340
01341 public:
01343 typedef typename pbase_type::pmode pmode;
01344
01346 typedef typename pbase_type::argv_type argv_type;
01347
01349 basic_opstream()
01350 : ostream_type(NULL), pbase_type()
01351 { }
01352
01363 basic_opstream(const std::string& command, pmode mode = pstdin)
01364 : ostream_type(NULL), pbase_type(command, mode|pstdin)
01365 { }
01366
01378 basic_opstream( const std::string& file,
01379 const argv_type& argv,
01380 pmode mode = pstdin )
01381 : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
01382 { }
01383
01389 ~basic_opstream() { }
01390
01400 void
01401 open(const std::string& command, pmode mode = pstdin)
01402 {
01403 this->do_open(command, mode|pstdin);
01404 }
01405
01416 void
01417 open( const std::string& file,
01418 const argv_type& argv,
01419 pmode mode = pstdin)
01420 {
01421 this->do_open(file, argv, mode|pstdin);
01422 }
01423 };
01424
01425
01441 template <typename CharT, typename Traits = std::char_traits<CharT> >
01442 class basic_pstream
01443 : public std::basic_iostream<CharT, Traits>
01444 , public pstream_common<CharT, Traits>
01445 , virtual public pstreams
01446 {
01447 typedef std::basic_iostream<CharT, Traits> iostream_type;
01448 typedef pstream_common<CharT, Traits> pbase_type;
01449
01450 using pbase_type::buf_;
01451
01452 public:
01454 typedef typename pbase_type::pmode pmode;
01455
01457 typedef typename pbase_type::argv_type argv_type;
01458
01460 basic_pstream()
01461 : iostream_type(NULL), pbase_type()
01462 { }
01463
01474 basic_pstream( const std::string& command,
01475 pmode mode = pstdout|pstdin )
01476 : iostream_type(NULL), pbase_type(command, mode)
01477 { }
01478
01490 basic_pstream( const std::string& file,
01491 const argv_type& argv,
01492 pmode mode = pstdout|pstdin )
01493 : iostream_type(NULL), pbase_type(file, argv, mode)
01494 { }
01495
01501 ~basic_pstream() { }
01502
01512 void
01513 open(const std::string& command, pmode mode = pstdout|pstdin)
01514 {
01515 this->do_open(command, mode);
01516 }
01517
01528 void
01529 open( const std::string& file,
01530 const argv_type& argv,
01531 pmode mode = pstdout|pstdin )
01532 {
01533 this->do_open(file, argv, mode);
01534 }
01535
01540 basic_pstream&
01541 out()
01542 {
01543 this->buf_.read_err(false);
01544 return *this;
01545 }
01546
01551 basic_pstream&
01552 err()
01553 {
01554 this->buf_.read_err(true);
01555 return *this;
01556 }
01557 };
01558
01559
01583 template <typename CharT, typename Traits = std::char_traits<CharT> >
01584 class basic_rpstream
01585 : public std::basic_ostream<CharT, Traits>
01586 , private std::basic_istream<CharT, Traits>
01587 , private pstream_common<CharT, Traits>
01588 , virtual public pstreams
01589 {
01590 typedef std::basic_ostream<CharT, Traits> ostream_type;
01591 typedef std::basic_istream<CharT, Traits> istream_type;
01592 typedef pstream_common<CharT, Traits> pbase_type;
01593
01594 using pbase_type::buf_;
01595
01596 public:
01598 typedef typename pbase_type::pmode pmode;
01599
01601 typedef typename pbase_type::argv_type argv_type;
01602
01604 basic_rpstream()
01605 : ostream_type(NULL) , istream_type(NULL) , pbase_type()
01606 { }
01607
01618 basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin)
01619 : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode)
01620 { }
01621
01633 basic_rpstream( const std::string& file,
01634 const argv_type& argv,
01635 pmode mode = pstdout|pstdin )
01636 : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
01637 { }
01638
01640 ~basic_rpstream() { }
01641
01652 void
01653 open(const std::string& command, pmode mode = pstdout|pstdin)
01654 {
01655 this->do_open(command, mode);
01656 }
01657
01670 void
01671 open( const std::string& file,
01672 const argv_type& argv,
01673 pmode mode = pstdout|pstdin )
01674 {
01675 this->do_open(file, argv, mode);
01676 }
01677
01683 istream_type&
01684 out()
01685 {
01686 this->buf_.read_err(false);
01687 return *this;
01688 }
01689
01695 istream_type&
01696 err()
01697 {
01698 this->buf_.read_err(true);
01699 return *this;
01700 }
01701 };
01702
01703
01706 typedef basic_pstreambuf<char> pstreambuf;
01709 typedef basic_ipstream<char> ipstream;
01712 typedef basic_opstream<char> opstream;
01715 typedef basic_pstream<char> pstream;
01718 typedef basic_rpstream<char> rpstream;
01719
01720
01735 template <typename C, typename T>
01736 inline std::basic_ostream<C,T>&
01737 peof(std::basic_ostream<C,T>& s)
01738 {
01739 typedef basic_pstreambuf<C,T> pstreambuf;
01740 if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf()))
01741 p->peof();
01742 return s;
01743 }
01744
01745
01746
01747
01748
01749
01750
01759 template <typename C, typename T>
01760 inline
01761 basic_pstreambuf<C,T>::basic_pstreambuf()
01762 : ppid_(-1)
01763 , wpipe_(-1)
01764 , wbuffer_(NULL)
01765 , rsrc_(rsrc_out)
01766 , status_(-1)
01767 , error_(0)
01768 {
01769 init_rbuffers();
01770 }
01771
01780 template <typename C, typename T>
01781 inline
01782 basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode)
01783 : ppid_(-1)
01784 , wpipe_(-1)
01785 , wbuffer_(NULL)
01786 , rsrc_(rsrc_out)
01787 , status_(-1)
01788 , error_(0)
01789 {
01790 init_rbuffers();
01791 open(command, mode);
01792 }
01793
01803 template <typename C, typename T>
01804 inline
01805 basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& file,
01806 const argv_type& argv,
01807 pmode mode )
01808 : ppid_(-1)
01809 , wpipe_(-1)
01810 , wbuffer_(NULL)
01811 , rsrc_(rsrc_out)
01812 , status_(-1)
01813 , error_(0)
01814 {
01815 init_rbuffers();
01816 open(file, argv, mode);
01817 }
01818
01823 template <typename C, typename T>
01824 inline
01825 basic_pstreambuf<C,T>::~basic_pstreambuf()
01826 {
01827 close();
01828 }
01829
01844 template <typename C, typename T>
01845 basic_pstreambuf<C,T>*
01846 basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
01847 {
01848 basic_pstreambuf<C,T>* ret = NULL;
01849
01850 if (!is_open())
01851 {
01852 switch(fork(mode))
01853 {
01854 case 0 :
01855 {
01856
01857 ::execlp("sh", "sh", "-c", command.c_str(), (void*)NULL);
01858
01859
01860
01861
01862 ::_exit(errno);
01863
01864 }
01865 case -1 :
01866 {
01867
01868 break;
01869 }
01870 default :
01871 {
01872
01873
01874 create_buffers(mode);
01875 ret = this;
01876 }
01877 }
01878 }
01879 return ret;
01880 }
01881
01898 template <typename C, typename T>
01899 basic_pstreambuf<C,T>*
01900 basic_pstreambuf<C,T>::open( const std::string& file,
01901 const argv_type& argv,
01902 pmode mode )
01903 {
01904 basic_pstreambuf<C,T>* ret = NULL;
01905
01906 if (!is_open())
01907 {
01908 switch(fork(mode))
01909 {
01910 case 0 :
01911 {
01912
01913
01914 char** arg_v = new char*[argv.size()+1];
01915 for (std::size_t i = 0; i < argv.size(); ++i)
01916 {
01917 const std::string& src = argv[i];
01918 char*& dest = arg_v[i];
01919 dest = new char[src.size()+1];
01920 dest[ src.copy(dest, src.size()) ] = '\0';
01921 }
01922 arg_v[argv.size()] = NULL;
01923
01924 ::execvp(file.c_str(), arg_v);
01925
01926
01927
01928
01929 ::_exit(errno);
01930
01931 }
01932 case -1 :
01933 {
01934
01935 break;
01936 }
01937 default :
01938 {
01939
01940
01941 create_buffers(mode);
01942 ret = this;
01943 }
01944 }
01945 }
01946 return ret;
01947 }
01948
01958 inline void
01959 close_fd_array(int* filedes, std::size_t count)
01960 {
01961 for (std::size_t i = 0; i < count; ++i)
01962 if (filedes[i] >= 0)
01963 if (::close(filedes[i]) == 0)
01964 filedes[i] = -1;
01965 }
01966
01983 template <typename C, typename T>
01984 pid_t
01985 basic_pstreambuf<C,T>::fork(pmode mode)
01986 {
01987 pid_t pid = -1;
01988
01989
01990
01991
01992 fd_type fd[6] = {-1, -1, -1, -1, -1, -1};
01993 fd_type* const pin = fd;
01994 fd_type* const pout = fd+2;
01995 fd_type* const perr = fd+4;
01996
01997
01998 const int RD = 0;
01999 const int WR = 1;
02000
02001
02002
02003
02004
02005 if (!error_ && mode&pstdin && ::pipe(pin))
02006 error_ = errno;
02007
02008 if (!error_ && mode&pstdout && ::pipe(pout))
02009 error_ = errno;
02010
02011 if (!error_ && mode&pstderr && ::pipe(perr))
02012 error_ = errno;
02013
02014 if (!error_)
02015 {
02016 pid = ::fork();
02017 switch (pid)
02018 {
02019 case 0 :
02020 {
02021
02022
02023
02024
02025
02026 if (*pin >= 0)
02027 {
02028 ::close(pin[WR]);
02029 ::dup2(pin[RD], STDIN_FILENO);
02030 ::close(pin[RD]);
02031 }
02032 if (*pout >= 0)
02033 {
02034 ::close(pout[RD]);
02035 ::dup2(pout[WR], STDOUT_FILENO);
02036 ::close(pout[WR]);
02037 }
02038 if (*perr >= 0)
02039 {
02040 ::close(perr[RD]);
02041 ::dup2(perr[WR], STDERR_FILENO);
02042 ::close(perr[WR]);
02043 }
02044 break;
02045 }
02046 case -1 :
02047 {
02048
02049 error_ = errno;
02050
02051 close_fd_array(fd, 6);
02052 break;
02053 }
02054 default :
02055 {
02056
02057 ppid_ = pid;
02058
02059
02060 if (*pin >= 0)
02061 {
02062 wpipe_ = pin[WR];
02063 ::close(pin[RD]);
02064 }
02065 if (*pout >= 0)
02066 {
02067 rpipe_[rsrc_out] = pout[RD];
02068 ::close(pout[WR]);
02069 }
02070 if (*perr >= 0)
02071 {
02072 rpipe_[rsrc_err] = perr[RD];
02073 ::close(perr[WR]);
02074 }
02075
02076 if (rpipe_[rsrc_out] == -1 && rpipe_[rsrc_err] >= 0)
02077 {
02078
02079 read_err(true);
02080 }
02081 }
02082 }
02083 }
02084 else
02085 {
02086
02087 close_fd_array(fd, 6);
02088 }
02089 return pid;
02090 }
02091
02101 template <typename C, typename T>
02102 basic_pstreambuf<C,T>*
02103 basic_pstreambuf<C,T>::close()
02104 {
02105 basic_pstreambuf<C,T>* ret = NULL;
02106 if (is_open())
02107 {
02108 sync();
02109
02110 destroy_buffers(pstdin|pstdout|pstderr);
02111
02112
02113 close_fd_array(&wpipe_, 1);
02114 close_fd_array(rpipe_, 2);
02115
02116 if (wait() == 1)
02117 {
02118 ret = this;
02119 }
02120 }
02121 return ret;
02122 }
02123
02127 template <typename C, typename T>
02128 inline void
02129 basic_pstreambuf<C,T>::init_rbuffers()
02130 {
02131 rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
02132 rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
02133 rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
02134 }
02135
02136 template <typename C, typename T>
02137 void
02138 basic_pstreambuf<C,T>::create_buffers(pmode mode)
02139 {
02140 if (mode & pstdin)
02141 {
02142 delete[] wbuffer_;
02143 wbuffer_ = new char_type[bufsz];
02144 this->setp(wbuffer_, wbuffer_ + bufsz);
02145 }
02146 if (mode & pstdout)
02147 {
02148 delete[] rbuffer_[rsrc_out];
02149 rbuffer_[rsrc_out] = new char_type[bufsz];
02150 if (rsrc_ == rsrc_out)
02151 this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
02152 rbuffer_[rsrc_out] + pbsz);
02153 }
02154 if (mode & pstderr)
02155 {
02156 delete[] rbuffer_[rsrc_err];
02157 rbuffer_[rsrc_err] = new char_type[bufsz];
02158 if (rsrc_ == rsrc_err)
02159 this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
02160 rbuffer_[rsrc_err] + pbsz);
02161 }
02162 }
02163
02164 template <typename C, typename T>
02165 void
02166 basic_pstreambuf<C,T>::destroy_buffers(pmode mode)
02167 {
02168 if (mode & pstdin)
02169 {
02170 this->setp(NULL, NULL);
02171 delete[] wbuffer_;
02172 wbuffer_ = NULL;
02173 }
02174 if (mode & pstdout)
02175 {
02176 if (rsrc_ == rsrc_out)
02177 this->setg(NULL, NULL, NULL);
02178 delete[] rbuffer_[rsrc_out];
02179 rbuffer_[rsrc_out] = NULL;
02180 }
02181 if (mode & pstderr)
02182 {
02183 if (rsrc_ == rsrc_err)
02184 this->setg(NULL, NULL, NULL);
02185 delete[] rbuffer_[rsrc_err];
02186 rbuffer_[rsrc_err] = NULL;
02187 }
02188 }
02189
02190 template <typename C, typename T>
02191 typename basic_pstreambuf<C,T>::buf_read_src
02192 basic_pstreambuf<C,T>::switch_read_buffer(buf_read_src src)
02193 {
02194 if (rsrc_ != src)
02195 {
02196 char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
02197 this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
02198 for (std::size_t i = 0; i < 3; ++i)
02199 rbufstate_[i] = tmpbufstate[i];
02200 rsrc_ = src;
02201 }
02202 return rsrc_;
02203 }
02204
02217 template <typename C, typename T>
02218 int
02219 basic_pstreambuf<C,T>::wait(bool nohang)
02220 {
02221 int exited = -1;
02222 if (is_open())
02223 {
02224 int status;
02225 switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0))
02226 {
02227 case 0 :
02228
02229 exited = 0;
02230 break;
02231 case -1 :
02232 error_ = errno;
02233 break;
02234 default :
02235
02236 ppid_ = 0;
02237 status_ = status;
02238 exited = 1;
02239 destroy_buffers(pstdin|pstdout|pstderr);
02240 close_fd_array(&wpipe_, 1);
02241 close_fd_array(rpipe_, 2);
02242 break;
02243 }
02244 }
02245 return exited;
02246 }
02247
02258 template <typename C, typename T>
02259 inline basic_pstreambuf<C,T>*
02260 basic_pstreambuf<C,T>::kill(int signal)
02261 {
02262 basic_pstreambuf<C,T>* ret = NULL;
02263 if (is_open())
02264 {
02265 if (::kill(ppid_, signal))
02266 error_ = errno;
02267 else
02268 {
02269
02270 ret = this;
02271 }
02272 }
02273 return ret;
02274 }
02275
02280 template <typename C, typename T>
02281 inline bool
02282 basic_pstreambuf<C,T>::exited()
02283 {
02284 return ppid_ == 0 || wait(true)==1;
02285 }
02286
02287
02293 template <typename C, typename T>
02294 inline int
02295 basic_pstreambuf<C,T>::status() const
02296 {
02297 return status_;
02298 }
02299
02303 template <typename C, typename T>
02304 inline int
02305 basic_pstreambuf<C,T>::error() const
02306 {
02307 return error_;
02308 }
02309
02314 template <typename C, typename T>
02315 inline void
02316 basic_pstreambuf<C,T>::peof()
02317 {
02318 sync();
02319 destroy_buffers(pstdin);
02320 close_fd_array(&wpipe_, 1);
02321 }
02322
02333 template <typename C, typename T>
02334 inline bool
02335 basic_pstreambuf<C,T>::is_open() const
02336 {
02337 return ppid_ > 0;
02338 }
02339
02348 template <typename C, typename T>
02349 inline bool
02350 basic_pstreambuf<C,T>::read_err(bool readerr)
02351 {
02352 buf_read_src src = readerr ? rsrc_err : rsrc_out;
02353 if (rpipe_[src]>=0)
02354 {
02355 switch_read_buffer(src);
02356 return true;
02357 }
02358 return false;
02359 }
02360
02371 template <typename C, typename T>
02372 typename basic_pstreambuf<C,T>::int_type
02373 basic_pstreambuf<C,T>::overflow(int_type c)
02374 {
02375 if (!empty_buffer())
02376 return traits_type::eof();
02377 else if (!traits_type::eq_int_type(c, traits_type::eof()))
02378 return this->sputc(c);
02379 else
02380 return traits_type::not_eof(c);
02381 }
02382
02383
02384 template <typename C, typename T>
02385 int
02386 basic_pstreambuf<C,T>::sync()
02387 {
02388 return !exited() && empty_buffer() ? 0 : -1;
02389 }
02390
02396 template <typename C, typename T>
02397 std::streamsize
02398 basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
02399 {
02400 if (n < this->epptr() - this->pptr())
02401 {
02402 std::memcpy(this->pptr(), s, n * sizeof(char_type));
02403 this->pbump(n);
02404 return n;
02405 }
02406 else
02407 {
02408 for (std::streamsize i = 0; i < n; ++i)
02409 {
02410 if (traits_type::eq_int_type(this->sputc(s[i]), traits_type::eof()))
02411 return i;
02412 }
02413 return n;
02414 }
02415 }
02416
02420 template <typename C, typename T>
02421 bool
02422 basic_pstreambuf<C,T>::empty_buffer()
02423 {
02424 const std::streamsize count = this->pptr() - this->pbase();
02425 const std::streamsize written = this->write(this->wbuffer_, count);
02426 if (count > 0 && written == count)
02427 {
02428 this->pbump(-written);
02429 return true;
02430 }
02431 return false;
02432 }
02433
02442 template <typename C, typename T>
02443 typename basic_pstreambuf<C,T>::int_type
02444 basic_pstreambuf<C,T>::underflow()
02445 {
02446 if (this->gptr() < this->egptr() || fill_buffer())
02447 return traits_type::to_int_type(*this->gptr());
02448 else
02449 return traits_type::eof();
02450 }
02451
02460 template <typename C, typename T>
02461 typename basic_pstreambuf<C,T>::int_type
02462 basic_pstreambuf<C,T>::pbackfail(int_type c)
02463 {
02464 if (this->gptr() != this->eback())
02465 {
02466 this->gbump(-1);
02467 if (!traits_type::eq_int_type(c, traits_type::eof()))
02468 *this->gptr() = traits_type::to_char_type(c);
02469 return traits_type::not_eof(c);
02470 }
02471 else
02472 return traits_type::eof();
02473 }
02474
02478 template <typename C, typename T>
02479 bool
02480 basic_pstreambuf<C,T>::fill_buffer()
02481 {
02482 const std::streamsize pb1 = this->gptr() - this->eback();
02483 const std::streamsize pb2 = pbsz;
02484 const std::streamsize npb = std::min(pb1, pb2);
02485
02486 std::memmove( rbuffer() + pbsz - npb,
02487 this->gptr() - npb,
02488 npb * sizeof(char_type) );
02489
02490 const std::streamsize rc = read(rbuffer() + pbsz, bufsz - pbsz);
02491
02492 if (rc > 0)
02493 {
02494 this->setg( rbuffer() + pbsz - npb,
02495 rbuffer() + pbsz,
02496 rbuffer() + pbsz + rc );
02497 return true;
02498 }
02499 else
02500 {
02501 this->setg(NULL, NULL, NULL);
02502 return false;
02503 }
02504 }
02505
02515 template <typename C, typename T>
02516 inline std::streamsize
02517 basic_pstreambuf<C,T>::write(char_type* s, std::streamsize n)
02518 {
02519 return wpipe() >= 0 ? ::write(wpipe(), s, n * sizeof(char_type)) : 0;
02520 }
02521
02531 template <typename C, typename T>
02532 inline std::streamsize
02533 basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
02534 {
02535 return rpipe() >= 0 ? ::read(rpipe(), s, n * sizeof(char_type)) : 0;
02536 }
02537
02539 template <typename C, typename T>
02540 inline typename basic_pstreambuf<C,T>::fd_type&
02541 basic_pstreambuf<C,T>::wpipe()
02542 {
02543 return wpipe_;
02544 }
02545
02547 template <typename C, typename T>
02548 inline typename basic_pstreambuf<C,T>::fd_type&
02549 basic_pstreambuf<C,T>::rpipe()
02550 {
02551 return rpipe_[rsrc_];
02552 }
02553
02555 template <typename C, typename T>
02556 inline typename basic_pstreambuf<C,T>::fd_type&
02557 basic_pstreambuf<C,T>::rpipe(buf_read_src which)
02558 {
02559 return rpipe_[which];
02560 }
02561
02563 template <typename C, typename T>
02564 inline typename basic_pstreambuf<C,T>::char_type*
02565 basic_pstreambuf<C,T>::rbuffer()
02566 {
02567 return rbuffer_[rsrc_];
02568 }
02569
02570
02571
02572
02573
02574
02586 template <typename C, typename T>
02587 inline
02588 pstream_common<C,T>::pstream_common()
02589 : std::basic_ios<C,T>(NULL)
02590 , command_()
02591 , buf_()
02592 {
02593 this->init(&buf_);
02594 }
02595
02604 template <typename C, typename T>
02605 inline
02606 pstream_common<C,T>::pstream_common(const std::string& command, pmode mode)
02607 : std::basic_ios<C,T>(NULL)
02608 , command_(command)
02609 , buf_()
02610 {
02611 this->init(&buf_);
02612 do_open(command, mode);
02613 }
02614
02624 template <typename C, typename T>
02625 inline
02626 pstream_common<C,T>::pstream_common( const std::string& file,
02627 const argv_type& argv,
02628 pmode mode )
02629 : std::basic_ios<C,T>(NULL)
02630 , command_(file)
02631 , buf_()
02632 {
02633 this->init(&buf_);
02634 do_open(file, argv, mode);
02635 }
02636
02646 template <typename C, typename T>
02647 inline
02648 pstream_common<C,T>::~pstream_common()
02649 {
02650 }
02651
02660 template <typename C, typename T>
02661 inline void
02662 pstream_common<C,T>::do_open(const std::string& command, pmode mode)
02663 {
02664 if (!buf_.open((command_=command), mode))
02665 this->setstate(std::ios::failbit);
02666 }
02667
02677 template <typename C, typename T>
02678 inline void
02679 pstream_common<C,T>::do_open( const std::string& file,
02680 const argv_type& argv,
02681 pmode mode )
02682 {
02683 if (!buf_.open((command_=file), argv, mode))
02684 this->setstate(std::ios::failbit);
02685 }
02686
02688 template <typename C, typename T>
02689 inline void
02690 pstream_common<C,T>::close()
02691 {
02692 if (!buf_.close())
02693 this->setstate(std::ios::failbit);
02694 }
02695
02700 template <typename C, typename T>
02701 inline bool
02702 pstream_common<C,T>::is_open() const
02703 {
02704 return buf_.is_open();
02705 }
02706
02708 template <typename C, typename T>
02709 inline const std::string&
02710 pstream_common<C,T>::command() const
02711 {
02712 return command_;
02713 }
02714
02716
02717 template <typename C, typename T>
02718 inline typename pstream_common<C,T>::streambuf_type*
02719 pstream_common<C,T>::rdbuf() const
02720 {
02721 return const_cast<streambuf_type*>(&buf_);
02722 }
02723
02724
02725 #if REDI_EVISCERATE_PSTREAMS
02726
02755 template <typename C, typename T>
02756 std::size_t
02757 basic_pstreambuf<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
02758 {
02759 in = out = err = NULL;
02760 std::size_t open_files = 0;
02761 if (wpipe() > -1)
02762 {
02763 if ((in = ::fdopen(wpipe(), "w")))
02764 {
02765 open_files |= pstdin;
02766 }
02767 }
02768 if (rpipe(rsrc_out) > -1)
02769 {
02770 if ((out = ::fdopen(rpipe(rsrc_out), "r")))
02771 {
02772 open_files |= pstdout;
02773 }
02774 }
02775 if (rpipe(rsrc_err) > -1)
02776 {
02777 if ((err = ::fdopen(rpipe(rsrc_err), "r")))
02778 {
02779 open_files |= pstderr;
02780 }
02781 }
02782 return open_files;
02783 }
02784
02795 template <typename C, typename T>
02796 inline std::size_t
02797 pstream_common<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
02798 {
02799 return buf_.fopen(in, out, err);
02800 }
02801
02802 #endif // REDI_EVISCERATE_PSTREAMS
02803
02804
02805 }
02806 }
02807
02808 #endif // defined(__GNUC__) && (__GNUC__ < 3)
02809
02810 #endif // REDI_PSTREAM_H_SEEN