1 /* $Id: pstream.h,v 1.90 2005/06/11 09:25:06 redi Exp $
2 PStreams - POSIX Process I/O for C++
3 Copyright (C) 2001,2002,2003,2004 Jonathan Wakely
4 
5 This file is part of PStreams.
6 
7 PStreams is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11 
12 PStreams is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with PStreams; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 /**
23  * @file pstream.h
24  * @brief Declares all PStreams classes.
25  * @author Jonathan Wakely
26  *
27  * Defines classes redi::ipstream, redi::opstream, redi::pstream
28  * and redi::rpstream.
29  */
30 
31 #ifndef REDI_PSTREAM_H_SEEN
32 #define REDI_PSTREAM_H_SEEN
33 
34 #include <ios>
35 #include <streambuf>
36 #include <istream>
37 #include <ostream>
38 #include <string>
39 #include <vector>
40 #include <algorithm>    // for min()
41 #include <cstring>      // for memcpy(), memmove() etc.
42 #include <cerrno>       // for errno
43 #include <cstddef>      // for size_t
44 #include <cstdlib>      // for exit()
45 #include <sys/types.h>  // for pid_t
46 #include <sys/wait.h>   // for waitpid()
47 #include <sys/ioctl.h>  // for ioctl() and FIONREAD
48 #if defined(__sun)
49 # include <sys/filio.h> // for FIONREAD on Solaris 2.5
50 #endif
51 #include <unistd.h>     // for pipe() fork() exec() and filedes functions
52 #include <signal.h>     // for kill()
53 #include <fcntl.h>      // for fcntl()
54 #if REDI_EVISCERATE_PSTREAMS
55 # include <stdio.h>     // for FILE, fdopen()
56 #endif
57 
58 
59 /// The library version.
60 #define PSTREAMS_VERSION 0x0052   // 0.5.2
61 
62 /**
63  *  @namespace redi
64  *  @brief  All PStreams classes are declared in namespace redi.
65  *
66  *  Like the standard IOStreams, PStreams is a set of class templates,
67  *  taking a character type and traits type. As with the standard streams
68  *  they are most likely to be used with @c char and the default
69  *  traits type, so typedefs for this most common case are provided.
70  *
71  *  The @c pstream_common class template is not intended to be used directly,
72  *  it is used internally to provide the common functionality for the
73  *  other stream classes.
74  */
75 namespace redi
76 {
77   /// Common base class providing constants and typenames.
78   struct pstreams
79   {
80     /// Type used to specify how to connect to the process.
81     typedef std::ios_base::openmode           pmode;
82 
83     /// Type used to hold the arguments for a command.
84     typedef std::vector<std::string>          argv_type;
85 
86     /// Type used for file descriptors.
87     typedef int                               fd_type;
88 
89     static const pmode pstdin  = std::ios_base::out; ///< Write to stdin
90     static const pmode pstdout = std::ios_base::in;  ///< Read from stdout
91     static const pmode pstderr = std::ios_base::app; ///< Read from stderr
92 
93   protected:
94     enum { bufsz = 32 };  ///< Size of pstreambuf buffers.
95     enum { pbsz  = 2 };   ///< Number of putback characters kept.
96   };
97 
98   /// Class template for stream buffer.
99   template <typename CharT, typename Traits = std::char_traits<CharT> >
100     class basic_pstreambuf
101     : public std::basic_streambuf<CharT, Traits>
102     , public pstreams
103     {
104     public:
105       // Type definitions for dependent types
106       typedef CharT                             char_type;
107       typedef Traits                            traits_type;
108       typedef typename traits_type::int_type    int_type;
109       typedef typename traits_type::off_type    off_type;
110       typedef typename traits_type::pos_type    pos_type;
111       /** @deprecated use pstreams::fd_type instead. */
112       typedef fd_type                           fd_t;
113       /* to have basic_pstreambuf::fd_type well-defined also out-of-scope */
114       typedef pstreams::fd_type                 fd_type;
115 
116       /// Default constructor.
117       basic_pstreambuf();
118 
119       /// Constructor that initialises the buffer with @a command.
120       basic_pstreambuf(const std::string& command, pmode mode);
121 
122       /// Constructor that initialises the buffer with @a file and @a argv.
123       basic_pstreambuf( const std::string& file,
124                         const argv_type& argv,
125                         pmode mode );
126 
127       /// Destructor.
128       ~basic_pstreambuf();
129 
130       /// Initialise the stream buffer with @a command.
131       basic_pstreambuf*
132       open(const std::string& command, pmode mode);
133 
134       /// Initialise the stream buffer with @a file and @a argv.
135       basic_pstreambuf*
136       open(const std::string& file, const argv_type& argv, pmode mode, const std::string& working_dir = "");
137 
138       /// Close the stream buffer and wait for the process to exit.
139       basic_pstreambuf*
140       close();
141 
142       /// Send a signal to the process.
143       basic_pstreambuf*
144       kill(int signal = SIGTERM);
145 
146       /// Close the pipe connected to the process' stdin.
147       void
148       peof();
149 
150       /// Change active input source.
151       bool
152       read_err(bool readerr = true);
153 
154       /// Report whether the stream buffer has been initialised.
155       bool
156       is_open() const;
157 
158       /// Report whether the process has exited.
159       bool
160       exited();
161 
162 #if REDI_EVISCERATE_PSTREAMS
163       /// Obtain FILE pointers for each of the process' standard streams.
164       std::size_t
165       fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
166 #endif
167 
168       /// Return the exit status of the process.
169       int
170       status() const;
171 
172       /// Return the error number for the most recent failed operation.
173       int
174       error() const;
175 
176     protected:
177       /// Transfer characters to the pipe when character buffer overflows.
178       int_type
179       overflow(int_type c);
180 
181       /// Transfer characters from the pipe when the character buffer is empty.
182       int_type
183       underflow();
184 
185       /// Make a character available to be returned by the next extraction.
186       int_type
187       pbackfail(int_type c = traits_type::eof());
188 
189       /// Write any buffered characters to the stream.
190       int
191       sync();
192 
193       /// Insert multiple characters into the pipe.
194       std::streamsize
195       xsputn(const char_type* s, std::streamsize n);
196 
197       /// Insert a sequence of characters into the pipe.
198       std::streamsize
199       write(const char_type* s, std::streamsize n);
200 
201       /// Extract a sequence of characters from the pipe.
202       std::streamsize
203       read(char_type* s, std::streamsize n);
204 
205       /// Report how many characters can be read from active input without blocking.
206       std::streamsize
207       showmanyc();
208 
209     protected:
210       /// Enumerated type to indicate whether stdout or stderr is to be read.
211       enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
212 
213       /// Initialise pipes and fork process.
214       pid_t
215       fork(pmode mode);
216 
217       /// Wait for the child process to exit.
218       int
219       wait(bool nohang = false);
220 
221       /// Return the file descriptor for the output pipe.
222       fd_type&
223       wpipe();
224 
225       /// Return the file descriptor for the active input pipe.
226       fd_type&
227       rpipe();
228 
229       /// Return the file descriptor for the specified input pipe.
230       fd_type&
231       rpipe(buf_read_src which);
232 
233       void
234       create_buffers(pmode mode);
235 
236       void
237       destroy_buffers(pmode mode);
238 
239       /// Writes buffered characters to the process' stdin pipe.
240       bool
241       empty_buffer();
242 
243       bool
244       fill_buffer();
245 
246       /// Return the active input buffer.
247       char_type*
248       rbuffer();
249 
250       buf_read_src
251       switch_read_buffer(buf_read_src);
252 
253     private:
254       basic_pstreambuf(const basic_pstreambuf&);
255       basic_pstreambuf& operator=(const basic_pstreambuf&);
256 
257       void
258       init_rbuffers();
259 
260       pid_t         ppid_;        // pid of process
261       fd_type       wpipe_;       // pipe used to write to process' stdin
262       fd_type       rpipe_[2];    // two pipes to read from, stdout and stderr
263       char_type*    wbuffer_;
264       char_type*    rbuffer_[2];
265       char_type*    rbufstate_[3];
266       /// Index into rpipe_[] to indicate active source for read operations.
267       buf_read_src  rsrc_;
268       int           status_;      // hold exit status of child process
269       int           error_;       // hold errno if fork() or exec() fails
270     };
271 
272   /// Class template for common base class.
273   template <typename CharT, typename Traits = std::char_traits<CharT> >
274     class pstream_common
275     : virtual public std::basic_ios<CharT, Traits>
276     , virtual public pstreams
277     {
278     protected:
279       typedef basic_pstreambuf<CharT, Traits>       streambuf_type;
280 
281       /// Default constructor.
282       pstream_common();
283 
284       /// Constructor that initialises the stream by starting a process.
285       pstream_common(const std::string& command, pmode mode);
286 
287       /// Constructor that initialises the stream by starting a process.
288       pstream_common(const std::string& file, const argv_type& argv, pmode mode);
289 
290       /// Pure virtual destructor.
291       virtual
292       ~pstream_common() = 0;
293 
294       /// Start a process.
295       void
296       do_open(const std::string& command, pmode mode);
297 
298       /// Start a process.
299       void
300 	do_open(const std::string& file, const argv_type& argv, pmode mode, const std::string& working_dir = "");
301 
302     public:
303       /// Close the pipe.
304       void
305       close();
306 
307       /// Report whether the stream's buffer has been initialised.
308       bool
309       is_open() const;
310 
311       /// Return the command used to initialise the stream.
312       const std::string&
313       command() const;
314 
315       /// Return a pointer to the stream buffer.
316       streambuf_type*
317       rdbuf() const;
318 
319 #if REDI_EVISCERATE_PSTREAMS
320       /// Obtain FILE pointers for each of the process' standard streams.
321       std::size_t
322       fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err);
323 #endif
324 
325     protected:
326       std::string       command_; ///< The command used to start the process.
327       streambuf_type    buf_;     ///< The stream buffer.
328     };
329 
330 
331   /**
332    * @class basic_ipstream
333    * @brief Class template for Input PStreams.
334    *
335    * Reading from an ipstream reads the command's standard output and/or
336    * standard error (depending on how the ipstream is opened)
337    * and the command's standard input is the same as that of the process
338    * that created the object, unless altered by the command itself.
339    */
340 
341   template <typename CharT, typename Traits = std::char_traits<CharT> >
342     class basic_ipstream
343     : public std::basic_istream<CharT, Traits>
344     , public pstream_common<CharT, Traits>
345     , virtual public pstreams
346     {
347       typedef std::basic_istream<CharT, Traits>     istream_type;
348       typedef pstream_common<CharT, Traits>         pbase_type;
349 
350       using pbase_type::buf_;  // declare name in this scope
351 
352     public:
353       /// Type used to specify how to connect to the process.
354       typedef typename pbase_type::pmode            pmode;
355 
356       /// Type used to hold the arguments for a command.
357       typedef typename pbase_type::argv_type        argv_type;
358 
359       /// Default constructor, creates an uninitialised stream.
basic_ipstream()360       basic_ipstream()
361       : istream_type(NULL), pbase_type()
362       { }
363 
364       /**
365        * @brief Constructor that initialises the stream by starting a process.
366        *
367        * Initialises the stream buffer by calling do_open() with the supplied
368        * arguments.
369        *
370        * @param command  a string containing a shell command.
371        * @param mode     the I/O mode to use when opening the pipe.
372        * @see   do_open(const std::string&, pmode)
373        */
374       basic_ipstream(const std::string& command, pmode mode = pstdout)
istream_type(NULL)375       : istream_type(NULL), pbase_type(command, mode|pstdout)
376       { }
377 
378       /**
379        * @brief Constructor that initialises the stream by starting a process.
380        *
381        * Initialises the stream buffer by calling do_open() with the supplied
382        * arguments.
383        *
384        * @param file  a string containing the pathname of a program to execute.
385        * @param argv  a vector of argument strings passed to the new program.
386        * @param mode  the I/O mode to use when opening the pipe.
387        * @see   do_open(const std::string&, const argv_type&, pmode)
388        */
389       basic_ipstream( const std::string& file,
390                       const argv_type& argv,
391                       pmode mode = pstdout )
istream_type(NULL)392       : istream_type(NULL), pbase_type(file, argv, mode|pstdout)
393       { }
394 
395       /**
396        * @brief Destructor.
397        *
398        * Closes the stream and waits for the child to exit.
399        */
~basic_ipstream()400       ~basic_ipstream()
401       { }
402 
403       /**
404        * @brief Start a process.
405        *
406        * Calls do_open( @a %command , @a mode|pstdout ).
407        *
408        * @param command  a string containing a shell command.
409        * @param mode     the I/O mode to use when opening the pipe.
410        * @see   do_open(const std::string&, pmode)
411        */
412       void
413       open(const std::string& command, pmode mode = pstdout)
414       {
415         this->do_open(command, mode|pstdout);
416       }
417 
418       /**
419        * @brief Start a process.
420        *
421        * Calls do_open( @a file , @a argv , @a mode|pstdout ).
422        *
423        * @param file  a string containing the pathname of a program to execute.
424        * @param argv  a vector of argument strings passed to the new program.
425        * @param mode  the I/O mode to use when opening the pipe.
426        * @see   do_open(const std::string&, const argv_type&, pmode)
427        */
428       void
429       open( const std::string& file,
430             const argv_type& argv,
431             pmode mode = pstdout )
432       {
433         this->do_open(file, argv, mode|pstdout);
434       }
435 
436       /**
437        * @brief Set streambuf to read from process' @c stdout.
438        * @return  @c *this
439        */
440       basic_ipstream&
out()441       out()
442       {
443         this->buf_.read_err(false);
444         return *this;
445       }
446 
447       /**
448        * @brief Set streambuf to read from process' @c stderr.
449        * @return  @c *this
450        */
451       basic_ipstream&
err()452       err()
453       {
454         this->buf_.read_err(true);
455         return *this;
456       }
457     };
458 
459 
460   /**
461    * @class basic_opstream
462    * @brief Class template for Output PStreams.
463    *
464    * Writing to an open opstream writes to the standard input of the command;
465    * the command's standard output is the same as that of the process that
466    * created the pstream object, unless altered by the command itself.
467    */
468 
469   template <typename CharT, typename Traits = std::char_traits<CharT> >
470     class basic_opstream
471     : public std::basic_ostream<CharT, Traits>
472     , public pstream_common<CharT, Traits>
473     , virtual public pstreams
474     {
475       typedef std::basic_ostream<CharT, Traits>     ostream_type;
476       typedef pstream_common<CharT, Traits>         pbase_type;
477 
478       using pbase_type::buf_;  // declare name in this scope
479 
480     public:
481       /// Type used to specify how to connect to the process.
482       typedef typename pbase_type::pmode            pmode;
483 
484       /// Type used to hold the arguments for a command.
485       typedef typename pbase_type::argv_type        argv_type;
486 
487       /// Default constructor, creates an uninitialised stream.
basic_opstream()488       basic_opstream()
489       : ostream_type(NULL), pbase_type()
490       { }
491 
492       /**
493        * @brief Constructor that initialises the stream by starting a process.
494        *
495        * Initialises the stream buffer by calling do_open() with the supplied
496        * arguments.
497        *
498        * @param command  a string containing a shell command.
499        * @param mode     the I/O mode to use when opening the pipe.
500        * @see   do_open(const std::string&, pmode)
501        */
502       basic_opstream(const std::string& command, pmode mode = pstdin)
ostream_type(NULL)503       : ostream_type(NULL), pbase_type(command, mode|pstdin)
504       { }
505 
506       /**
507        * @brief Constructor that initialises the stream by starting a process.
508        *
509        * Initialises the stream buffer by calling do_open() with the supplied
510        * arguments.
511        *
512        * @param file  a string containing the pathname of a program to execute.
513        * @param argv  a vector of argument strings passed to the new program.
514        * @param mode  the I/O mode to use when opening the pipe.
515        * @see   do_open(const std::string&, const argv_type&, pmode)
516        */
517       basic_opstream( const std::string& file,
518                       const argv_type& argv,
519                       pmode mode = pstdin )
ostream_type(NULL)520       : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
521       { }
522 
523       /**
524        * @brief Destructor
525        *
526        * Closes the stream and waits for the child to exit.
527        */
~basic_opstream()528       ~basic_opstream() { }
529 
530       /**
531        * @brief Start a process.
532        *
533        * Calls do_open( @a %command , @a mode|pstdin ).
534        *
535        * @param command  a string containing a shell command.
536        * @param mode     the I/O mode to use when opening the pipe.
537        * @see   do_open(const std::string&, pmode)
538        */
539       void
540       open(const std::string& command, pmode mode = pstdin)
541       {
542         this->do_open(command, mode|pstdin);
543       }
544 
545       /**
546        * @brief Start a process.
547        *
548        * Calls do_open( @a file , @a argv , @a mode|pstdin ).
549        *
550        * @param file  a string containing the pathname of a program to execute.
551        * @param argv  a vector of argument strings passed to the new program.
552        * @param mode  the I/O mode to use when opening the pipe.
553        * @see   do_open(const std::string&, const argv_type&, pmode)
554        */
555       void
556       open( const std::string& file,
557             const argv_type& argv,
558             pmode mode = pstdin)
559       {
560         this->do_open(file, argv, mode|pstdin);
561       }
562     };
563 
564 
565   /**
566    * @class basic_pstream
567    * @brief Class template for Bidirectional PStreams.
568    *
569    * Writing to a pstream opened with @c pmode @c pstdin writes to the
570    * standard input of the command.
571    * Reading from a pstream opened with @c pmode @c pstdout and/or @c pstderr
572    * reads the command's standard output and/or standard error.
573    * Any of the process' @c stdin, @c stdout or @c stderr that is not
574    * connected to the pstream (as specified by the @c pmode)
575    * will be the same as the process that created the pstream object,
576    * unless altered by the command itself.
577    */
578   template <typename CharT, typename Traits = std::char_traits<CharT> >
579     class basic_pstream
580     : public std::basic_iostream<CharT, Traits>
581     , public pstream_common<CharT, Traits>
582     , virtual public pstreams
583     {
584       typedef std::basic_iostream<CharT, Traits>    iostream_type;
585       typedef pstream_common<CharT, Traits>         pbase_type;
586 
587       using pbase_type::buf_;  // declare name in this scope
588 
589     public:
590       /// Type used to specify how to connect to the process.
591       typedef typename pbase_type::pmode            pmode;
592 
593       /// Type used to hold the arguments for a command.
594       typedef typename pbase_type::argv_type        argv_type;
595 
596       /// Default constructor, creates an uninitialised stream.
basic_pstream()597       basic_pstream()
598       : iostream_type(NULL), pbase_type()
599       { }
600 
601       /**
602        * @brief Constructor that initialises the stream by starting a process.
603        *
604        * Initialises the stream buffer by calling do_open() with the supplied
605        * arguments.
606        *
607        * @param command  a string containing a shell command.
608        * @param mode     the I/O mode to use when opening the pipe.
609        * @see   do_open(const std::string&, pmode)
610        */
611       basic_pstream(const std::string& command, pmode mode = pstdout|pstdin)
iostream_type(NULL)612       : iostream_type(NULL), pbase_type(command, mode)
613       { }
614 
615       /**
616        * @brief Constructor that initialises the stream by starting a process.
617        *
618        * Initialises the stream buffer by calling do_open() with the supplied
619        * arguments.
620        *
621        * @param file  a string containing the pathname of a program to execute.
622        * @param argv  a vector of argument strings passed to the new program.
623        * @param mode  the I/O mode to use when opening the pipe.
624        * @see   do_open(const std::string&, const argv_type&, pmode)
625        */
626       basic_pstream( const std::string& file,
627                      const argv_type& argv,
628                      pmode mode = pstdout|pstdin )
iostream_type(NULL)629       : iostream_type(NULL), pbase_type(file, argv, mode)
630       { }
631 
632       /**
633        * @brief Destructor
634        *
635        * Closes the stream and waits for the child to exit.
636        */
~basic_pstream()637       ~basic_pstream() { }
638 
639       /**
640        * @brief Start a process.
641        *
642        * Calls do_open( @a %command , @a mode ).
643        *
644        * @param command  a string containing a shell command.
645        * @param mode     the I/O mode to use when opening the pipe.
646        * @see   do_open(const std::string&, pmode)
647        */
648       void
649       open(const std::string& command, pmode mode = pstdout|pstdin)
650       {
651         this->do_open(command, mode);
652       }
653 
654       /**
655        * @brief Start a process.
656        *
657        * Calls do_open( @a file , @a argv , @a mode ).
658        *
659        * @param file  a string containing the pathname of a program to execute.
660        * @param argv  a vector of argument strings passed to the new program.
661        * @param mode  the I/O mode to use when opening the pipe.
662        * @see   do_open(const std::string&, const argv_type&, pmode)
663        */
664       void
665       open( const std::string& file,
666             const argv_type& argv,
667             pmode mode = pstdout|pstdin,
668 		   const std::string& working_dir = "" )
669       {
670         this->do_open(file, argv, mode, working_dir);
671       }
672 
673       /**
674        * @brief Set streambuf to read from process' @c stdout.
675        * @return  @c *this
676        */
677       basic_pstream&
out()678       out()
679       {
680         this->buf_.read_err(false);
681         return *this;
682       }
683 
684       /**
685        * @brief Set streambuf to read from process' @c stderr.
686        * @return  @c *this
687        */
688       basic_pstream&
err()689       err()
690       {
691         this->buf_.read_err(true);
692         return *this;
693       }
694     };
695 
696 
697   /**
698    * @class basic_rpstream
699    * @brief template for Restricted PStreams.
700    *
701    * Writing to an rpstream opened with @c pmode @c pstdin writes to the
702    * standard input of the command.
703    * It is not possible to read directly from an rpstream object, to use
704    * an rpstream as in istream you must call either basic_rpstream::out()
705    * or basic_rpstream::err(). This is to prevent accidental reads from
706    * the wrong input source. If the rpstream was not opened with @c pmode
707    * @c pstderr then the class cannot read the process' @c stderr, and
708    * basic_rpstream::err() will return an istream that reads from the
709    * process' @c stdout, and vice versa.
710    * Reading from an rpstream opened with @c pmode @c pstdout and/or
711    * @c pstderr reads the command's standard output and/or standard error.
712    * Any of the process' @c stdin, @c stdout or @c stderr that is not
713    * connected to the pstream (as specified by the @c pmode)
714    * will be the same as the process that created the pstream object,
715    * unless altered by the command itself.
716    */
717 
718   template <typename CharT, typename Traits = std::char_traits<CharT> >
719     class basic_rpstream
720     : public std::basic_ostream<CharT, Traits>
721     , private std::basic_istream<CharT, Traits>
722     , private pstream_common<CharT, Traits>
723     , virtual public pstreams
724     {
725       typedef std::basic_ostream<CharT, Traits>     ostream_type;
726       typedef std::basic_istream<CharT, Traits>     istream_type;
727       typedef pstream_common<CharT, Traits>         pbase_type;
728 
729       using pbase_type::buf_;  // declare name in this scope
730 
731     public:
732       /// Type used to specify how to connect to the process.
733       typedef typename pbase_type::pmode            pmode;
734 
735       /// Type used to hold the arguments for a command.
736       typedef typename pbase_type::argv_type        argv_type;
737 
738       /// Default constructor, creates an uninitialised stream.
basic_rpstream()739       basic_rpstream()
740       : ostream_type(NULL), istream_type(NULL), pbase_type()
741       { }
742 
743       /**
744        * @brief  Constructor that initialises the stream by starting a process.
745        *
746        * Initialises the stream buffer by calling do_open() with the supplied
747        * arguments.
748        *
749        * @param command a string containing a shell command.
750        * @param mode the I/O mode to use when opening the pipe.
751        * @see   do_open(const std::string&, pmode)
752        */
753       basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin)
ostream_type(NULL)754       : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode)
755       { }
756 
757       /**
758        * @brief  Constructor that initialises the stream by starting a process.
759        *
760        * Initialises the stream buffer by calling do_open() with the supplied
761        * arguments.
762        *
763        * @param file a string containing the pathname of a program to execute.
764        * @param argv a vector of argument strings passed to the new program.
765        * @param mode the I/O mode to use when opening the pipe.
766        * @see   do_open(const std::string&, const argv_type&, pmode)
767        */
768       basic_rpstream( const std::string& file,
769                       const argv_type& argv,
770                       pmode mode = pstdout|pstdin )
ostream_type(NULL)771       : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
772       { }
773 
774       /// Destructor
~basic_rpstream()775       ~basic_rpstream() { }
776 
777       /**
778        * @brief  Start a process.
779        *
780        * Calls do_open( @a %command , @a mode ).
781        *
782        * @param command a string containing a shell command.
783        * @param mode the I/O mode to use when opening the pipe.
784        * @see   do_open(const std::string&, pmode)
785        */
786       void
787       open(const std::string& command, pmode mode = pstdout|pstdin)
788       {
789         this->do_open(command, mode);
790       }
791 
792       /**
793        * @brief  Start a process.
794        *
795        * Calls do_open( @a file , @a argv , @a mode ).
796        *
797        * @param file a string containing the pathname of a program to execute.
798        * @param argv a vector of argument strings passed to the new program.
799        * @param mode the I/O mode to use when opening the pipe.
800        * @see   do_open(const std::string&, const argv_type&, pmode)
801        */
802       void
803       open( const std::string& file,
804             const argv_type& argv,
805             pmode mode = pstdout|pstdin )
806       {
807         this->do_open(file, argv, mode);
808       }
809 
810       /**
811        * @brief  Obtain a reference to the istream that reads
812        *         the process' @c stdout.
813        * @return @c *this
814        */
815       istream_type&
out()816       out()
817       {
818         this->buf_.read_err(false);
819         return *this;
820       }
821 
822       /**
823        * @brief  Obtain a reference to the istream that reads
824        *         the process' @c stderr.
825        * @return @c *this
826        */
827       istream_type&
err()828       err()
829       {
830         this->buf_.read_err(true);
831         return *this;
832       }
833     };
834 
835 
836   /// Type definition for common template specialisation.
837   typedef basic_pstreambuf<char> pstreambuf;
838   /// Type definition for common template specialisation.
839   typedef basic_ipstream<char> ipstream;
840   /// Type definition for common template specialisation.
841   typedef basic_opstream<char> opstream;
842   /// Type definition for common template specialisation.
843   typedef basic_pstream<char> pstream;
844   /// Type definition for common template specialisation.
845   typedef basic_rpstream<char> rpstream;
846 
847 
848   /**
849    * When inserted into an output pstream the manipulator calls
850    * basic_pstreambuf<C,T>::peof() to close the output pipe,
851    * causing the child process to receive the end-of-file indicator
852    * on subsequent reads from its @c stdin stream.
853    *
854    * @brief   Manipulator to close the pipe connected to the process' stdin.
855    * @param   s  An output PStream class.
856    * @return  The stream object the manipulator was invoked on.
857    * @see     basic_pstreambuf<C,T>::peof()
858    * @relates basic_opstream basic_pstream basic_rpstream
859    */
860   template <typename C, typename T>
861     inline std::basic_ostream<C,T>&
peof(std::basic_ostream<C,T> & s)862     peof(std::basic_ostream<C,T>& s)
863     {
864       typedef basic_pstreambuf<C,T> pstreambuf;
865 		if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf()))
866 		  p->peof();
867       return s;
868     }
869 
870 
871   /*
872    * member definitions for pstreambuf
873    */
874 
875 
876   /**
877    * @class basic_pstreambuf
878    * Provides underlying streambuf functionality for the PStreams classes.
879    */
880 
881   /** Creates an uninitialised stream buffer. */
882   template <typename C, typename T>
883     inline
basic_pstreambuf()884     basic_pstreambuf<C,T>::basic_pstreambuf()
885     : ppid_(-1)   // initialise to -1 to indicate no process run yet.
886     , wpipe_(-1)
887     , wbuffer_(NULL)
888     , rsrc_(rsrc_out)
889     , status_(-1)
890     , error_(0)
891     {
892       init_rbuffers();
893     }
894 
895   /**
896    * Initialises the stream buffer by calling open() with the supplied
897    * arguments.
898    *
899    * @param command a string containing a shell command.
900    * @param mode    the I/O mode to use when opening the pipe.
901    * @see   open()
902    */
903   template <typename C, typename T>
904     inline
basic_pstreambuf(const std::string & command,pmode mode)905     basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode)
906     : ppid_(-1)   // initialise to -1 to indicate no process run yet.
907     , wpipe_(-1)
908     , wbuffer_(NULL)
909     , rsrc_(rsrc_out)
910     , status_(-1)
911     , error_(0)
912     {
913       init_rbuffers();
914       open(command, mode);
915     }
916 
917   /**
918    * Initialises the stream buffer by calling open() with the supplied
919    * arguments.
920    *
921    * @param file  a string containing the name of a program to execute.
922    * @param argv  a vector of argument strings passsed to the new program.
923    * @param mode  the I/O mode to use when opening the pipe.
924    * @see   open()
925    */
926   template <typename C, typename T>
927     inline
basic_pstreambuf(const std::string & file,const argv_type & argv,pmode mode)928     basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& file,
929                                              const argv_type& argv,
930                                              pmode mode )
931     : ppid_(-1)   // initialise to -1 to indicate no process run yet.
932     , wpipe_(-1)
933     , wbuffer_(NULL)
934     , rsrc_(rsrc_out)
935     , status_(-1)
936     , error_(0)
937     {
938       init_rbuffers();
939       open(file, argv, mode);
940     }
941 
942   /**
943    * Closes the stream by calling close().
944    * @see close()
945    */
946   template <typename C, typename T>
947     inline
~basic_pstreambuf()948     basic_pstreambuf<C,T>::~basic_pstreambuf()
949     {
950       close();
951     }
952 
953   /**
954    * Starts a new process by passing @a command to the shell
955    * and opens pipes to the process with the specified @a mode.
956    *
957    * Will duplicate the actions of  the  shell  in searching for an
958    * executable file if the specified file name does not contain a slash (/)
959    * character.
960    *
961    * There is no way to tell whether the shell command succeeded, this
962    * function will always succeed unless resource limits (such as
963    * memory usage, or number of processes or open files) are exceeded.
964    * This means is_open() will return true even if @a command cannot
965    * be executed.
966    *
967    * @param   command  a string containing a shell command.
968    * @param   mode     a bitwise OR of one or more of @c out, @c in, @c err.
969    * @return  NULL if the shell could not be started or the
970    *          pipes could not be opened, @c this otherwise.
971    * @see     <b>execlp</b>(3)
972    */
973   template <typename C, typename T>
974     basic_pstreambuf<C,T>*
open(const std::string & command,pmode mode)975     basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
976     {
977 #if 0
978       const std::string argv[] = { "sh", "-c", command };
979       return this->open("sh", std::vector<std::string>(argv, argv+3), mode);
980 #else
981       basic_pstreambuf<C,T>* ret = NULL;
982 
983       if (!is_open())
984       {
985         switch(fork(mode))
986         {
987         case 0 :
988           // this is the new process, exec command
989           ::execlp("sh", "sh", "-c", command.c_str(), (void*)NULL);
990 
991           // can only reach this point if exec() failed
992 
993           // parent can get exit code from waitpid()
994           ::_exit(errno);
995           // using std::exit() would make static dtors run twice
996 
997         case -1 :
998           // couldn't fork, error already handled in pstreambuf::fork()
999           break;
1000 
1001         default :
1002           // this is the parent process
1003           // activate buffers
1004           create_buffers(mode);
1005           ret = this;
1006         }
1007       }
1008       return ret;
1009 #endif
1010     }
1011 
1012   /**
1013    * @brief  Helper function to close a file descriptor.
1014    *
1015    * Inspects @a fd and calls <b>close</b>(3) if it has a non-negative value.
1016    *
1017    * @param   fd  a file descriptor.
1018    * @relates basic_pstreambuf
1019    */
1020   inline void
close_fd(pstreams::fd_type & fd)1021   close_fd(pstreams::fd_type& fd)
1022   {
1023     if (fd >= 0 && ::close(fd) == 0)
1024       fd = -1;
1025   }
1026 
1027   /**
1028    * @brief  Helper function to close an array of file descriptors.
1029    *
1030    * Calls @c close_fd() on each member of the array.
1031    * The length of the array is determined automatically by
1032    * template argument deduction to avoid errors.
1033    *
1034    * @param   fds  an array of file descriptors.
1035    * @relates basic_pstreambuf
1036    */
1037   template <int N>
1038     inline void
close_fd_array(pstreams::fd_type (& fds)[N])1039     close_fd_array(pstreams::fd_type (&fds)[N])
1040     {
1041       for (std::size_t i = 0; i < N; ++i)
1042         close_fd(fds[i]);
1043     }
1044 
1045   /**
1046    * Starts a new process by executing @a file with the arguments in
1047    * @a argv and opens pipes to the process with the specified @a mode.
1048    *
1049    * By convention @c argv[0] should be the file name of the file being
1050    * executed.
1051    * Will duplicate the actions of  the  shell  in searching for an
1052    * executable file if the specified file name does not contain a slash (/)
1053    * character.
1054    *
1055    * Iff @a file is successfully executed then is_open() will return true.
1056    * Note that exited() will return true if file cannot be executed, since
1057    * the child process will have exited.
1058    *
1059    * @param   file  a string containing the pathname of a program to execute.
1060    * @param   argv  a vector of argument strings passed to the new program.
1061    * @param   mode  a bitwise OR of one or more of @c out, @c in and @c err.
1062    * @return  NULL if a pipe could not be opened or if the program could
1063    *          not be executed, @c this otherwise.
1064    * @see     <b>execvp</b>(3)
1065    */
1066   template <typename C, typename T>
1067     basic_pstreambuf<C,T>*
open(const std::string & file,const argv_type & argv,pmode mode,const std::string & working_dir)1068     basic_pstreambuf<C,T>::open( const std::string& file,
1069                                  const argv_type& argv,
1070 								pmode mode, const std::string& working_dir )
1071     {
1072       basic_pstreambuf<C,T>* ret = NULL;
1073 
1074       if (!is_open())
1075       {
1076         // constants for read/write ends of pipe
1077         enum { RD, WR };
1078 
1079         // open another pipe and set close-on-exec
1080         fd_type ck_exec[] = { -1, -1 };
1081         if (-1 == ::pipe(ck_exec)
1082             || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC)
1083             || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC))
1084         {
1085           error_ = errno;
1086           close_fd_array(ck_exec);
1087         }
1088         else
1089         {
1090           switch(fork(mode))
1091           {
1092           case 0 :
1093             // this is the new process, exec command
1094             {
1095 				if(working_dir != "") {
1096 					if(chdir(working_dir.c_str()) == -1)
1097 						::_exit(errno);
1098 				}
1099               char** arg_v = new char*[argv.size()+1];
1100               for (std::size_t i = 0; i < argv.size(); ++i)
1101               {
1102                 const std::string& src = argv[i];
1103                 char*& dest = arg_v[i];
1104                 dest = new char[src.size()+1];
1105                 dest[ src.copy(dest, src.size()) ] = '\0';
1106               }
1107               arg_v[argv.size()] = NULL;
1108 
1109               ::execvp(file.c_str(), arg_v);
1110 
1111               // can only reach this point if exec() failed
1112 
1113               // parent can get error code from ck_exec pipe
1114               error_ = errno;
1115 
1116               if(::write(ck_exec[WR], &error_, sizeof(error_)) < 0); // ignore error
1117               ::close(ck_exec[WR]);
1118               ::close(ck_exec[RD]);
1119 
1120               ::_exit(error_);
1121               // using std::exit() would make static dtors run twice
1122             }
1123 
1124           case -1 :
1125             // couldn't fork, error already handled in pstreambuf::fork()
1126             close_fd_array(ck_exec);
1127             break;
1128 
1129           default :
1130             // this is the parent process
1131 
1132             // check child called exec() successfully
1133             ::close(ck_exec[WR]);
1134             switch (::read(ck_exec[RD], &error_, sizeof(error_)))
1135             {
1136             case 0:
1137               // activate buffers
1138               create_buffers(mode);
1139               ret = this;
1140               break;
1141             case -1:
1142               error_ = errno;
1143               break;
1144             default:
1145               // error_ contains error code from child
1146               // call wait() to clean up and set ppid_ to 0
1147               this->wait();
1148               break;
1149             }
1150             ::close(ck_exec[RD]);
1151           }
1152         }
1153       }
1154       return ret;
1155     }
1156 
1157   /**
1158    * Creates pipes as specified by @a mode and calls @c fork() to create
1159    * a new process. If the fork is successful the parent process stores
1160    * the child's PID and the opened pipes and the child process replaces
1161    * its standard streams with the opened pipes.
1162    *
1163    * If an error occurs the error code will be set to one of the possile
1164    * errors for @c pipe() or @c fork().
1165    * See your system's documentation for these error codes.
1166    *
1167    * @param   mode  an OR of pmodes specifying which of the child's
1168    *                standard streams to connect to.
1169    * @return  On success the PID of the child is returned in the parent's
1170    *          context and zero is returned in the child's context.
1171    *          On error -1 is returned and the error code is set appropriately.
1172    */
1173   template <typename C, typename T>
1174     pid_t
fork(pmode mode)1175     basic_pstreambuf<C,T>::fork(pmode mode)
1176     {
1177       pid_t pid = -1;
1178 
1179       // Three pairs of file descriptors, for pipes connected to the
1180       // process' stdin, stdout and stderr
1181       // (stored in a single array so close_fd_array() can close all at once)
1182       fd_type fd[] = { -1, -1, -1, -1, -1, -1 };
1183       fd_type* const pin = fd;
1184       fd_type* const pout = fd+2;
1185       fd_type* const perr = fd+4;
1186 
1187       // constants for read/write ends of pipe
1188       enum { RD, WR };
1189 
1190       // N.B.
1191       // For the pstreambuf pin is an output stream and
1192       // pout and perr are input streams.
1193 
1194       if (!error_ && mode&pstdin && ::pipe(pin))
1195         error_ = errno;
1196 
1197       if (!error_ && mode&pstdout && ::pipe(pout))
1198         error_ = errno;
1199 
1200       if (!error_ && mode&pstderr && ::pipe(perr))
1201         error_ = errno;
1202 
1203       if (!error_)
1204       {
1205         pid = ::fork();
1206         switch (pid)
1207         {
1208           case 0 :
1209           {
1210             // this is the new process
1211 
1212             // for each open pipe close one end and redirect the
1213             // respective standard stream to the other end
1214 
1215             if (*pin >= 0)
1216             {
1217               ::close(pin[WR]);
1218               ::dup2(pin[RD], STDIN_FILENO);
1219               ::close(pin[RD]);
1220             }
1221             if (*pout >= 0)
1222             {
1223               ::close(pout[RD]);
1224               ::dup2(pout[WR], STDOUT_FILENO);
1225               ::close(pout[WR]);
1226             }
1227             if (*perr >= 0)
1228             {
1229               ::close(perr[RD]);
1230               ::dup2(perr[WR], STDERR_FILENO);
1231               ::close(perr[WR]);
1232             }
1233             break;
1234           }
1235           case -1 :
1236           {
1237             // couldn't fork for some reason
1238             error_ = errno;
1239             // close any open pipes
1240             close_fd_array(fd);
1241             break;
1242           }
1243           default :
1244           {
1245             // this is the parent process, store process' pid
1246             ppid_ = pid;
1247 
1248             // store one end of open pipes and close other end
1249             if (*pin >= 0)
1250             {
1251               wpipe_ = pin[WR];
1252               ::close(pin[RD]);
1253             }
1254             if (*pout >= 0)
1255             {
1256               rpipe_[rsrc_out] = pout[RD];
1257               ::close(pout[WR]);
1258             }
1259             if (*perr >= 0)
1260             {
1261               rpipe_[rsrc_err] = perr[RD];
1262               ::close(perr[WR]);
1263             }
1264 
1265             if (rpipe_[rsrc_out] == -1 && rpipe_[rsrc_err] >= 0)
1266             {
1267               // reading stderr but not stdout, so use stderr for all reads
1268               read_err(true);
1269             }
1270           }
1271         }
1272       }
1273       else
1274       {
1275         // close any pipes we opened before failure
1276         close_fd_array(fd);
1277       }
1278       return pid;
1279     }
1280 
1281   /**
1282    * Closes all pipes and calls wait() to wait for the process to finish.
1283    * If an error occurs the error code will be set to one of the possible
1284    * errors for @c waitpid().
1285    * See your system's documentation for these errors.
1286    *
1287    * @return  @c this on successful close or @c NULL if there is no
1288    *          process to close or if an error occurs.
1289    */
1290   template <typename C, typename T>
1291     basic_pstreambuf<C,T>*
close()1292     basic_pstreambuf<C,T>::close()
1293     {
1294       basic_pstreambuf<C,T>* ret = NULL;
1295       if (is_open())
1296       {
1297         sync();
1298 
1299         destroy_buffers(pstdin|pstdout|pstderr);
1300 
1301         // close pipes before wait() so child gets EOF/SIGPIPE
1302         close_fd(wpipe_);
1303         close_fd_array(rpipe_);
1304 
1305         if (wait() == 1)
1306         {
1307           ret = this;
1308         }
1309       }
1310       return ret;
1311     }
1312 
1313   /**
1314    *  Called on construction to initialise the arrays used for reading.
1315    */
1316   template <typename C, typename T>
1317     inline void
init_rbuffers()1318     basic_pstreambuf<C,T>::init_rbuffers()
1319     {
1320       rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
1321       rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
1322       rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
1323     }
1324 
1325   template <typename C, typename T>
1326     void
create_buffers(pmode mode)1327     basic_pstreambuf<C,T>::create_buffers(pmode mode)
1328     {
1329       if (mode & pstdin)
1330       {
1331         delete[] wbuffer_;
1332         wbuffer_ = new char_type[bufsz];
1333         this->setp(wbuffer_, wbuffer_ + bufsz);
1334       }
1335       if (mode & pstdout)
1336       {
1337         delete[] rbuffer_[rsrc_out];
1338         rbuffer_[rsrc_out] = new char_type[bufsz];
1339         if (rsrc_ == rsrc_out)
1340           this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
1341               rbuffer_[rsrc_out] + pbsz);
1342       }
1343       if (mode & pstderr)
1344       {
1345         delete[] rbuffer_[rsrc_err];
1346         rbuffer_[rsrc_err] = new char_type[bufsz];
1347         if (rsrc_ == rsrc_err)
1348           this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
1349               rbuffer_[rsrc_err] + pbsz);
1350       }
1351     }
1352 
1353   template <typename C, typename T>
1354     void
destroy_buffers(pmode mode)1355     basic_pstreambuf<C,T>::destroy_buffers(pmode mode)
1356     {
1357       if (mode & pstdin)
1358       {
1359         this->setp(NULL, NULL);
1360         delete[] wbuffer_;
1361         wbuffer_ = NULL;
1362       }
1363       if (mode & pstdout)
1364       {
1365         if (rsrc_ == rsrc_out)
1366           this->setg(NULL, NULL, NULL);
1367         delete[] rbuffer_[rsrc_out];
1368         rbuffer_[rsrc_out] = NULL;
1369       }
1370       if (mode & pstderr)
1371       {
1372         if (rsrc_ == rsrc_err)
1373           this->setg(NULL, NULL, NULL);
1374         delete[] rbuffer_[rsrc_err];
1375         rbuffer_[rsrc_err] = NULL;
1376       }
1377     }
1378 
1379   template <typename C, typename T>
1380     typename basic_pstreambuf<C,T>::buf_read_src
switch_read_buffer(buf_read_src src)1381     basic_pstreambuf<C,T>::switch_read_buffer(buf_read_src src)
1382     {
1383       if (rsrc_ != src)
1384       {
1385         char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
1386         this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
1387         for (std::size_t i = 0; i < 3; ++i)
1388           rbufstate_[i] = tmpbufstate[i];
1389         rsrc_ = src;
1390       }
1391       return rsrc_;
1392     }
1393 
1394   /**
1395    * Suspends execution and waits for the associated process to exit, or
1396    * until a signal is delivered whose action is to terminate the current
1397    * process or to call a signal handling function. If the process has
1398    * already exited wait() returns immediately.
1399    *
1400    * @param   nohang  true to return immediately if the process has not exited.
1401    * @return  1 if the process has exited.
1402    *          0 if @a nohang is true and the process has not exited yet.
1403    *          -1 if no process has been started or if an error occurs,
1404    *          in which case the error can be found using error().
1405    */
1406   template <typename C, typename T>
1407     int
wait(bool nohang)1408     basic_pstreambuf<C,T>::wait(bool nohang)
1409     {
1410       int exited = -1;
1411       if (is_open())
1412       {
1413         int status;
1414         switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0))
1415         {
1416           case 0 :
1417             // nohang was true and process has not exited
1418             exited = 0;
1419             break;
1420           case -1 :
1421             error_ = errno;
1422             break;
1423           default :
1424             // process has exited
1425             ppid_ = 0;
1426             status_ = status;
1427             exited = 1;
1428             destroy_buffers(pstdin|pstdout|pstderr);
1429             close_fd(wpipe_);
1430             close_fd_array(rpipe_);
1431             break;
1432         }
1433       }
1434       return exited;
1435     }
1436 
1437   /**
1438    * Sends the specified signal to the process.  A signal can be used to
1439    * terminate a child process that would not exit otherwise.
1440    *
1441    * If an error occurs the error code will be set to one of the possible
1442    * errors for @c kill().  See your system's documentation for these errors.
1443    *
1444    * @param   signal  A signal to send to the child process.
1445    * @return  @c this or @c NULL if @c kill() fails.
1446    */
1447   template <typename C, typename T>
1448     inline basic_pstreambuf<C,T>*
kill(int signal)1449     basic_pstreambuf<C,T>::kill(int signal)
1450     {
1451       basic_pstreambuf<C,T>* ret = NULL;
1452       if (is_open())
1453       {
1454         if (::kill(ppid_, signal))
1455           error_ = errno;
1456         else
1457         {
1458           // TODO call exited() to check for exit and clean up? leave to user?
1459           ret = this;
1460         }
1461       }
1462       return ret;
1463     }
1464 
1465   /**
1466    *  @return  True if the associated process has exited, false otherwise.
1467    *  @see     basic_pstreambuf<C,T>::close()
1468    */
1469   template <typename C, typename T>
1470     inline bool
exited()1471     basic_pstreambuf<C,T>::exited()
1472     {
1473       return ppid_ == 0 || wait(true)==1;
1474     }
1475 
1476 
1477   /**
1478    *  @return  The exit status of the child process, or -1 if close()
1479    *           has not yet been called to wait for the child to exit.
1480    *  @see     basic_pstreambuf<C,T>::close()
1481    */
1482   template <typename C, typename T>
1483     inline int
status()1484     basic_pstreambuf<C,T>::status() const
1485     {
1486       return status_;
1487     }
1488 
1489   /**
1490    *  @return  The error code of the most recently failed operation, or zero.
1491    */
1492   template <typename C, typename T>
1493     inline int
error()1494     basic_pstreambuf<C,T>::error() const
1495     {
1496       return error_;
1497     }
1498 
1499   /**
1500    *  Closes the output pipe, causing the child process to receive the
1501    *  end-of-file indicator on subsequent reads from its @c stdin stream.
1502    */
1503   template <typename C, typename T>
1504     inline void
peof()1505     basic_pstreambuf<C,T>::peof()
1506     {
1507       sync();
1508       destroy_buffers(pstdin);
1509       close_fd(wpipe_);
1510     }
1511 
1512   /**
1513    * @return  true if a previous call to open() succeeded and wait() has
1514    *          not been called and determined that the process has exited,
1515    *          false otherwise.
1516    * @warning This function can not be used to determine whether the
1517    *          command used to initialise the buffer was successfully
1518    *          executed or not. If the shell command failed this function
1519    *          will still return true.
1520    *          You can use exited() to see if it's still open.
1521    */
1522   template <typename C, typename T>
1523     inline bool
is_open()1524     basic_pstreambuf<C,T>::is_open() const
1525     {
1526       return ppid_ > 0;
1527     }
1528 
1529   /**
1530    * Toggle the stream used for reading. If @a readerr is @c true then the
1531    * process' @c stderr output will be used for subsequent extractions, if
1532    * @a readerr is false the the process' stdout will be used.
1533    * @param   readerr  @c true to read @c stderr, @c false to read @c stdout.
1534    * @return  @c true if the requested stream is open and will be used for
1535    *          subsequent extractions, @c false otherwise.
1536    */
1537   template <typename C, typename T>
1538     inline bool
read_err(bool readerr)1539     basic_pstreambuf<C,T>::read_err(bool readerr)
1540     {
1541       buf_read_src src = readerr ? rsrc_err : rsrc_out;
1542       if (rpipe_[src]>=0)
1543       {
1544         switch_read_buffer(src);
1545         return true;
1546       }
1547       return false;
1548     }
1549 
1550   /**
1551    * Called when the internal character buffer is not present or is full,
1552    * to transfer the buffer contents to the pipe.
1553    *
1554    * @param   c  a character to be written to the pipe.
1555    * @return  @c traits_type::not_eof(c) if @a c is equal to @c
1556    *          traits_type::eof(). Otherwise returns @a c if @a c can be
1557    *          written to the pipe, or @c traits_type::eof() if not.
1558    */
1559   template <typename C, typename T>
1560     typename basic_pstreambuf<C,T>::int_type
overflow(int_type c)1561     basic_pstreambuf<C,T>::overflow(int_type c)
1562     {
1563       if (!empty_buffer())
1564         return traits_type::eof();
1565       else if (!traits_type::eq_int_type(c, traits_type::eof()))
1566         return this->sputc(c);
1567       else
1568         return traits_type::not_eof(c);
1569     }
1570 
1571 
1572   template <typename C, typename T>
1573     int
sync()1574     basic_pstreambuf<C,T>::sync()
1575     {
1576       return !exited() && empty_buffer() ? 0 : -1;
1577     }
1578 
1579   /**
1580    * @param   s  character buffer.
1581    * @param   n  buffer length.
1582    * @return  the number of characters written.
1583    */
1584   template <typename C, typename T>
1585     std::streamsize
xsputn(const char_type * s,std::streamsize n)1586     basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
1587     {
1588       if (n < this->epptr() - this->pptr())
1589       {
1590         std::memcpy(this->pptr(), s, n * sizeof(char_type));
1591         this->pbump(n);
1592         return n;
1593       }
1594       else
1595       {
1596         for (std::streamsize i = 0; i < n; ++i)
1597         {
1598           if (traits_type::eq_int_type(this->sputc(s[i]), traits_type::eof()))
1599             return i;
1600         }
1601         return n;
1602       }
1603     }
1604 
1605   /**
1606    * @return  true if the buffer was emptied, false otherwise.
1607    */
1608   template <typename C, typename T>
1609     bool
empty_buffer()1610     basic_pstreambuf<C,T>::empty_buffer()
1611     {
1612       const std::streamsize count = this->pptr() - this->pbase();
1613       const std::streamsize written = this->write(this->wbuffer_, count);
1614       if (count > 0 && written == count)
1615       {
1616         this->pbump(-written);
1617         return true;
1618       }
1619       return false;
1620     }
1621 
1622   /**
1623    * Called when the internal character buffer is is empty, to re-fill it
1624    * from the pipe.
1625    *
1626    * @return The first available character in the buffer,
1627    * or @c traits_type::eof() in case of failure.
1628    */
1629   template <typename C, typename T>
1630     typename basic_pstreambuf<C,T>::int_type
underflow()1631     basic_pstreambuf<C,T>::underflow()
1632     {
1633       if (this->gptr() < this->egptr() || fill_buffer())
1634         return traits_type::to_int_type(*this->gptr());
1635       else
1636         return traits_type::eof();
1637     }
1638 
1639   /**
1640    * Attempts to make @a c available as the next character to be read by
1641    * @c sgetc().
1642    *
1643    * @param   c   a character to make available for extraction.
1644    * @return  @a c if the character can be made available,
1645    *          @c traits_type::eof() otherwise.
1646    */
1647   template <typename C, typename T>
1648     typename basic_pstreambuf<C,T>::int_type
pbackfail(int_type c)1649     basic_pstreambuf<C,T>::pbackfail(int_type c)
1650     {
1651       if (this->gptr() != this->eback())
1652       {
1653         this->gbump(-1);
1654         if (!traits_type::eq_int_type(c, traits_type::eof()))
1655           *this->gptr() = traits_type::to_char_type(c);
1656         return traits_type::not_eof(c);
1657       }
1658       else
1659          return traits_type::eof();
1660     }
1661 
1662   template <typename C, typename T>
1663     std::streamsize
showmanyc()1664     basic_pstreambuf<C,T>::showmanyc()
1665     {
1666       int avail = 0;
1667 #ifdef FIONREAD
1668       if (ioctl(rpipe(), FIONREAD, &avail) == -1)
1669         avail = -1;
1670       else
1671 #endif
1672       if (const std::ptrdiff_t buflen = this->gptr() - this->eback())
1673         avail += buflen;
1674       return std::streamsize(avail);
1675     }
1676 
1677   /**
1678    * @return  true if the buffer was filled, false otherwise.
1679    */
1680   template <typename C, typename T>
1681     bool
fill_buffer()1682     basic_pstreambuf<C,T>::fill_buffer()
1683     {
1684       const std::streamsize pb1 = this->gptr() - this->eback();
1685       const std::streamsize pb2 = pbsz;
1686       const std::streamsize npb = std::min(pb1, pb2);
1687 
1688       std::memmove( rbuffer() + pbsz - npb,
1689                     this->gptr() - npb,
1690                     npb * sizeof(char_type) );
1691 
1692       const std::streamsize rc = read(rbuffer() + pbsz, bufsz - pbsz);
1693 
1694       if (rc > 0)
1695       {
1696         this->setg( rbuffer() + pbsz - npb,
1697                     rbuffer() + pbsz,
1698                     rbuffer() + pbsz + rc );
1699         return true;
1700       }
1701       else
1702       {
1703         this->setg(NULL, NULL, NULL);
1704         return false;
1705       }
1706     }
1707 
1708   /**
1709    * Writes up to @a n characters to the pipe from the buffer @a s.
1710    * This currently only works for fixed width character encodings where
1711    * each character uses @c sizeof(char_type) bytes.
1712    *
1713    * @param   s  character buffer.
1714    * @param   n  buffer length.
1715    * @return  the number of characters written.
1716    */
1717   template <typename C, typename T>
1718     inline std::streamsize
write(const char_type * s,std::streamsize n)1719     basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n)
1720     {
1721       return wpipe() >= 0 ? ::write(wpipe(), s, n * sizeof(char_type)) : 0;
1722     }
1723 
1724   /**
1725    * Reads up to @a n characters from the pipe to the buffer @a s.
1726    * This currently only works for fixed width character encodings where
1727    * each character uses @c sizeof(char_type) bytes.
1728    *
1729    * @param   s  character buffer.
1730    * @param   n  buffer length.
1731    * @return  the number of characters read.
1732    */
1733   template <typename C, typename T>
1734     inline std::streamsize
read(char_type * s,std::streamsize n)1735     basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
1736     {
1737       return rpipe() >= 0 ? ::read(rpipe(), s, n * sizeof(char_type)) : 0;
1738     }
1739 
1740   /** @return a reference to the output file descriptor */
1741   template <typename C, typename T>
1742     inline typename basic_pstreambuf<C,T>::fd_type&
wpipe()1743     basic_pstreambuf<C,T>::wpipe()
1744     {
1745       return wpipe_;
1746     }
1747 
1748   /** @return a reference to the active input file descriptor */
1749   template <typename C, typename T>
1750     inline typename basic_pstreambuf<C,T>::fd_type&
rpipe()1751     basic_pstreambuf<C,T>::rpipe()
1752     {
1753       return rpipe_[rsrc_];
1754     }
1755 
1756   /** @return a reference to the specified input file descriptor */
1757   template <typename C, typename T>
1758     inline typename basic_pstreambuf<C,T>::fd_type&
rpipe(buf_read_src which)1759     basic_pstreambuf<C,T>::rpipe(buf_read_src which)
1760     {
1761       return rpipe_[which];
1762     }
1763 
1764   /** @return a pointer to the start of the active input buffer area. */
1765   template <typename C, typename T>
1766     inline typename basic_pstreambuf<C,T>::char_type*
rbuffer()1767     basic_pstreambuf<C,T>::rbuffer()
1768     {
1769       return rbuffer_[rsrc_];
1770     }
1771 
1772 
1773   /*
1774    * member definitions for pstream_common
1775    */
1776 
1777   /**
1778    * @class pstream_common
1779    * Abstract Base Class providing common functionality for basic_ipstream,
1780    * basic_opstream and basic_pstream.
1781    * pstream_common manages the basic_pstreambuf stream buffer that is used
1782    * by the derived classes to initialise an IOStream class.
1783    */
1784 
1785   /** Creates an uninitialised stream. */
1786   template <typename C, typename T>
1787     inline
pstream_common()1788     pstream_common<C,T>::pstream_common()
1789     : std::basic_ios<C,T>(NULL)
1790     , command_()
1791     , buf_()
1792     {
1793       this->init(&buf_);
1794     }
1795 
1796   /**
1797    * Initialises the stream buffer by calling
1798    * do_open( @a command , @a mode )
1799    *
1800    * @param command a string containing a shell command.
1801    * @param mode    the I/O mode to use when opening the pipe.
1802    * @see   do_open(const std::string&, pmode)
1803    */
1804   template <typename C, typename T>
1805     inline
pstream_common(const std::string & command,pmode mode)1806     pstream_common<C,T>::pstream_common(const std::string& command, pmode mode)
1807     : std::basic_ios<C,T>(NULL)
1808     , command_(command)
1809     , buf_()
1810     {
1811       this->init(&buf_);
1812       do_open(command, mode);
1813     }
1814 
1815   /**
1816    * Initialises the stream buffer by calling
1817    * do_open( @a file , @a argv , @a mode )
1818    *
1819    * @param file  a string containing the pathname of a program to execute.
1820    * @param argv  a vector of argument strings passed to the new program.
1821    * @param mode  the I/O mode to use when opening the pipe.
1822    * @see do_open(const std::string&, const argv_type&, pmode)
1823    */
1824   template <typename C, typename T>
1825     inline
pstream_common(const std::string & file,const argv_type & argv,pmode mode)1826     pstream_common<C,T>::pstream_common( const std::string& file,
1827                                          const argv_type& argv,
1828                                          pmode mode )
1829     : std::basic_ios<C,T>(NULL)
1830     , command_(file)
1831     , buf_()
1832     {
1833       this->init(&buf_);
1834       do_open(file, argv, mode);
1835     }
1836 
1837   /**
1838    * This is a pure virtual function to make @c pstream_common abstract.
1839    * Because it is the destructor it will be called by derived classes
1840    * and so must be defined.  It is also protected, to discourage use of
1841    * the PStreams classes through pointers or references to the base class.
1842    *
1843    * @sa If defining a pure virtual seems odd you should read
1844    * http://www.gotw.ca/gotw/031.htm (and the rest of the site as well!)
1845    */
1846   template <typename C, typename T>
1847     inline
~pstream_common()1848     pstream_common<C,T>::~pstream_common()
1849     {
1850     }
1851 
1852   /**
1853    * Calls rdbuf()->open( @a command , @a mode )
1854    * and sets @c failbit on error.
1855    *
1856    * @param command a string containing a shell command.
1857    * @param mode    the I/O mode to use when opening the pipe.
1858    * @see   basic_pstreambuf::open(const std::string&, pmode)
1859    */
1860   template <typename C, typename T>
1861     inline void
do_open(const std::string & command,pmode mode)1862     pstream_common<C,T>::do_open(const std::string& command, pmode mode)
1863     {
1864       if (!buf_.open((command_=command), mode))
1865         this->setstate(std::ios_base::failbit);
1866     }
1867 
1868   /**
1869    * Calls rdbuf()->open( @a file, @a  argv, @a mode )
1870    * and sets @c failbit on error.
1871    *
1872    * @param file  a string containing the pathname of a program to execute.
1873    * @param argv  a vector of argument strings passed to the new program.
1874    * @param mode  the I/O mode to use when opening the pipe.
1875    * @see   basic_pstreambuf::open(const std::string&, const argv_type&, pmode)
1876    */
1877   template <typename C, typename T>
1878     inline void
do_open(const std::string & file,const argv_type & argv,pmode mode,const std::string & working_dir)1879     pstream_common<C,T>::do_open( const std::string& file,
1880                                   const argv_type& argv,
1881 								 pmode mode, const std::string& working_dir )
1882     {
1883       if (!buf_.open((command_=file), argv, mode, working_dir))
1884         this->setstate(std::ios_base::failbit);
1885     }
1886 
1887   /** Calls rdbuf->close() and sets @c failbit on error. */
1888   template <typename C, typename T>
1889     inline void
close()1890     pstream_common<C,T>::close()
1891     {
1892       if (!buf_.close())
1893         this->setstate(std::ios_base::failbit);
1894     }
1895 
1896   /**
1897    * @return  rdbuf()->is_open().
1898    * @see     basic_pstreambuf::is_open()
1899    */
1900   template <typename C, typename T>
1901     inline bool
is_open()1902     pstream_common<C,T>::is_open() const
1903     {
1904       return buf_.is_open();
1905     }
1906 
1907   /** @return a string containing the command used to initialise the stream. */
1908   template <typename C, typename T>
1909     inline const std::string&
command()1910     pstream_common<C,T>::command() const
1911     {
1912       return command_;
1913     }
1914 
1915   /** @return a pointer to the private stream buffer member. */
1916   // TODO  document behaviour if buffer replaced.
1917   template <typename C, typename T>
1918     inline typename pstream_common<C,T>::streambuf_type*
rdbuf()1919     pstream_common<C,T>::rdbuf() const
1920     {
1921       return const_cast<streambuf_type*>(&buf_);
1922     }
1923 
1924 
1925 #if REDI_EVISCERATE_PSTREAMS
1926   /**
1927    * @def REDI_EVISCERATE_PSTREAMS
1928    * If this macro has a non-zero value then certain internals of the
1929    * @c basic_pstreambuf template class are exposed. In general this is
1930    * a Bad Thing, as the internal implementation is largely undocumented
1931    * and may be subject to change at any time, so this feature is only
1932    * provided because it might make PStreams useful in situations where
1933    * it is necessary to do Bad Things.
1934    */
1935 
1936   /**
1937    * @warning  This function exposes the internals of the stream buffer and
1938    *           should be used with caution. It is the caller's responsibility
1939    *           to flush streams etc. in order to clear any buffered data.
1940    *           The POSIX.1 function <b>fdopen</b>(3) is used to obtain the
1941    *           @c FILE pointers from the streambuf's private file descriptor
1942    *           members so consult your system's documentation for
1943    *           <b>fdopen</b>(3).
1944    *
1945    * @param   in    A FILE* that will refer to the process' stdin.
1946    * @param   out   A FILE* that will refer to the process' stdout.
1947    * @param   err   A FILE* that will refer to the process' stderr.
1948    * @return  An OR of zero or more of @c pstdin, @c pstdout, @c pstderr.
1949    *
1950    * For each open stream shared with the child process a @c FILE* is
1951    * obtained and assigned to the corresponding parameter. For closed
1952    * streams @c NULL is assigned to the parameter.
1953    * The return value can be tested to see which parameters should be
1954    * @c !NULL by masking with the corresponding @c pmode value.
1955    *
1956    * @see <b>fdopen</b>(3)
1957    */
1958   template <typename C, typename T>
1959     std::size_t
fopen(std::FILE * & in,std::FILE * & out,std::FILE * & err)1960     basic_pstreambuf<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
1961     {
1962       in = out = err = NULL;
1963       std::size_t open_files = 0;
1964       if (wpipe() > -1)
1965       {
1966         if ((in = ::fdopen(wpipe(), "w")))
1967         {
1968             open_files |= pstdin;
1969         }
1970       }
1971       if (rpipe(rsrc_out) > -1)
1972       {
1973         if ((out = ::fdopen(rpipe(rsrc_out), "r")))
1974         {
1975             open_files |= pstdout;
1976         }
1977       }
1978       if (rpipe(rsrc_err) > -1)
1979       {
1980         if ((err = ::fdopen(rpipe(rsrc_err), "r")))
1981         {
1982             open_files |= pstderr;
1983         }
1984       }
1985       return open_files;
1986     }
1987 
1988   /**
1989    *  @warning This function exposes the internals of the stream buffer and
1990    *  should be used with caution.
1991    *
1992    *  @param  in   A FILE* that will refer to the process' stdin.
1993    *  @param  out  A FILE* that will refer to the process' stdout.
1994    *  @param  err  A FILE* that will refer to the process' stderr.
1995    *  @return A bitwise-or of zero or more of @c pstdin, @c pstdout, @c pstderr.
1996    *  @see    basic_pstreambuf::fopen()
1997    */
1998   template <typename C, typename T>
1999     inline std::size_t
fopen(std::FILE * & in,std::FILE * & out,std::FILE * & err)2000     pstream_common<C,T>::fopen(std::FILE*& in, std::FILE*& out, std::FILE*& err)
2001     {
2002       return buf_.fopen(in, out, err);
2003     }
2004 
2005 #endif // REDI_EVISCERATE_PSTREAMS
2006 
2007 
2008 } // namespace redi
2009 
2010 /**
2011  * @mainpage PStreams Reference
2012  * @htmlinclude mainpage.html
2013  */
2014 
2015 #endif  // REDI_PSTREAM_H_SEEN
2016 
2017 // vim: ts=2 sw=2 expandtab
2018 
2019