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