added possibility to pass string to stdin of child process
This commit is contained in:
		
							
								
								
									
										140
									
								
								mrw/exec.cpp
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								mrw/exec.cpp
									
									
									
									
									
								
							@@ -9,6 +9,9 @@
 | 
				
			|||||||
    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
					    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $Log$
 | 
					    $Log$
 | 
				
			||||||
 | 
					    Revision 1.5  2004/12/14 20:30:09  marc
 | 
				
			||||||
 | 
					    added possibility to pass string to stdin of child process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Revision 1.4  2004/08/28 16:21:25  marc
 | 
					    Revision 1.4  2004/08/28 16:21:25  marc
 | 
				
			||||||
    mrw-c++-0.92 (mrw)
 | 
					    mrw-c++-0.92 (mrw)
 | 
				
			||||||
    - new file: version.cpp
 | 
					    - new file: version.cpp
 | 
				
			||||||
@@ -26,9 +29,11 @@
 | 
				
			|||||||
#include <mrw/exec.hpp>
 | 
					#include <mrw/exec.hpp>
 | 
				
			||||||
#include <mrw/unistd.hpp>
 | 
					#include <mrw/unistd.hpp>
 | 
				
			||||||
#include <mrw/exception.hpp>
 | 
					#include <mrw/exception.hpp>
 | 
				
			||||||
 | 
					#include <mrw/stdext.hpp> // max
 | 
				
			||||||
#include <sys/wait.h> // waitpid
 | 
					#include <sys/wait.h> // waitpid
 | 
				
			||||||
#include <unistd.h> // fork, exec
 | 
					#include <unistd.h> // fork, exec
 | 
				
			||||||
#include <string.h>  // memcpy
 | 
					#include <string.h>  // memcpy
 | 
				
			||||||
 | 
					#include <assert.h> // assert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
 | 
					mrw::ExecutionFailedExc::ExecutionFailedExc(const std::string& w,
 | 
				
			||||||
                                            const std::string& c)
 | 
					                                            const std::string& c)
 | 
				
			||||||
@@ -73,8 +78,13 @@ mrw::Cmd::operator mrw::Exec() const throw(std::bad_exception) {
 | 
				
			|||||||
  return mrw::Exec(*this);
 | 
					  return mrw::Exec(*this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mrw::Exec mrw::Cmd::execute(bool throwExc) const throw(std::exception) {
 | 
					mrw::Exec mrw::Cmd::execute(bool exc) const throw(std::exception) {
 | 
				
			||||||
  return mrw::Exec(*this).execute(throwExc);
 | 
					  return mrw::Exec(*this).execute(exc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mrw::Exec mrw::Cmd::execute(const std::string& input, bool exc) const
 | 
				
			||||||
 | 
					  throw(std::exception) {
 | 
				
			||||||
 | 
					  return mrw::Exec(*this).execute(input, exc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char* mrw::Cmd::path() const throw(std::bad_exception) {
 | 
					const char* mrw::Cmd::path() const throw(std::bad_exception) {
 | 
				
			||||||
@@ -109,10 +119,11 @@ mrw::Exec& mrw::Exec::operator=(const mrw::Exec& e) throw(std::bad_exception) {
 | 
				
			|||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mrw::Exec& mrw::Exec::execute(bool throwExc) throw(std::exception) {
 | 
					mrw::Exec& mrw::Exec::execute(bool exc) throw(std::exception) {
 | 
				
			||||||
  /** This method calls @c fork, sets up a pipe connection to pass @c
 | 
					  /** This method calls @c fork, sets up a pipe connection to pass @c
 | 
				
			||||||
      stdout and @c stderr from the child process to the parent process
 | 
					      stdout and @c stderr from the child process to the parent
 | 
				
			||||||
      using mrw::Pipe and calls @c execvp to execute the program. */
 | 
					      process using mrw::Pipe and calls @c execvp to execute the
 | 
				
			||||||
 | 
					      program. */
 | 
				
			||||||
  _success = false;
 | 
					  _success = false;
 | 
				
			||||||
  _res = _err = "";
 | 
					  _res = _err = "";
 | 
				
			||||||
  mrw::Pipe stdOut, stdErr;
 | 
					  mrw::Pipe stdOut, stdErr;
 | 
				
			||||||
@@ -128,17 +139,18 @@ mrw::Exec& mrw::Exec::execute(bool throwExc) throw(std::exception) {
 | 
				
			|||||||
      throw ExecutionFailedExc("cannot close pipe", *_cmd);
 | 
					      throw ExecutionFailedExc("cannot close pipe", *_cmd);
 | 
				
			||||||
    int num1(0), num2(0);
 | 
					    int num1(0), num2(0);
 | 
				
			||||||
    for (char buf1[4096], buf2[4096];
 | 
					    for (char buf1[4096], buf2[4096];
 | 
				
			||||||
         (num1=read(stdOut.istream(), buf1, sizeof(buf1)))>0 ||
 | 
					         (num1=read(stdOut.istream(), buf1, sizeof(buf1)))>0
 | 
				
			||||||
           num1==-1 && errno==EINTR ||
 | 
					           || num1==-1 && (errno==EINTR||errno==EAGAIN)
 | 
				
			||||||
           (num2=read(stdErr.istream(), buf2, sizeof(buf2)))>0 ||
 | 
					           || (num2=read(stdErr.istream(), buf2, sizeof(buf2)))>0
 | 
				
			||||||
           num2==-1 && errno==EINTR;
 | 
					           || num2==-1 && (errno==EINTR||errno==EAGAIN);) {
 | 
				
			||||||
         _res += std::string(buf1, num1), _err += std::string(buf2, num2));
 | 
					      if (num1>0) _res += std::string(buf1, num1);
 | 
				
			||||||
    if (num1==-1 || num2==-1)
 | 
					      if (num2>0) _err += std::string(buf2, num2);
 | 
				
			||||||
      throw ExecutionFailedExc("cannot_ read pipe", *_cmd);
 | 
					    }
 | 
				
			||||||
    // wait for child to get return code
 | 
					    // wait for child to get return code
 | 
				
			||||||
    int s(0);
 | 
					    int s(0);
 | 
				
			||||||
    if (waitpid(pid, &s, 0)!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0) {
 | 
					    if (waitpid(pid, &s, 0)!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0
 | 
				
			||||||
      if (throwExc) {
 | 
					        || num1==-1 || num2==-1) {
 | 
				
			||||||
 | 
					      if (exc) {
 | 
				
			||||||
        throw ExecutionFailedExc("execution failed", *_cmd);
 | 
					        throw ExecutionFailedExc("execution failed", *_cmd);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        _success = false;
 | 
					        _success = false;
 | 
				
			||||||
@@ -157,6 +169,106 @@ mrw::Exec& mrw::Exec::execute(bool throwExc) throw(std::exception) {
 | 
				
			|||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mrw::Exec& mrw::Exec::execute(const std::string& input, bool exc)
 | 
				
			||||||
 | 
					  throw(std::exception) {
 | 
				
			||||||
 | 
					  /// @c input length must be smaller than @c SSIZE_MAX.
 | 
				
			||||||
 | 
					  /// I'll only add support for longer strings upon request.
 | 
				
			||||||
 | 
					  assert(input.size()<=SSIZE_MAX &&
 | 
				
			||||||
 | 
					         "sdin input exeeds C library limit in mrw::Exec "
 | 
				
			||||||
 | 
					         "please contact the author of the library");
 | 
				
			||||||
 | 
					  /** This method calls @c fork, sets up a pipe connection to pass @c
 | 
				
			||||||
 | 
					      stdin, @c stdout and @c stderr from the child process to the
 | 
				
			||||||
 | 
					      parent process using mrw::Pipe and calls @c execvp to execute
 | 
				
			||||||
 | 
					      the program. */
 | 
				
			||||||
 | 
					  _success = false;
 | 
				
			||||||
 | 
					  _res = _err = "";
 | 
				
			||||||
 | 
					  mrw::Pipe stdIn(true), // child terminates if stdin is non-blocking
 | 
				
			||||||
 | 
					     stdOut, stdErr;
 | 
				
			||||||
 | 
					  if (!stdIn || !stdOut || !stdErr)
 | 
				
			||||||
 | 
					    throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
 | 
				
			||||||
 | 
					  pid_t pid(fork());
 | 
				
			||||||
 | 
					  if (pid<0) throw ExecutionFailedExc("cannot fork", *_cmd);
 | 
				
			||||||
 | 
					  if (pid) { // parent
 | 
				
			||||||
 | 
					    stdIn.close_in();
 | 
				
			||||||
 | 
					    stdOut.close_out();
 | 
				
			||||||
 | 
					    stdErr.close_out();
 | 
				
			||||||
 | 
					    if (!stdIn || !stdOut || !stdErr)
 | 
				
			||||||
 | 
					      throw ExecutionFailedExc("cannot close pipes", *_cmd);
 | 
				
			||||||
 | 
					    ssize_t num0(-1), num1(-1), num2(-1);
 | 
				
			||||||
 | 
					    std::string in(input);
 | 
				
			||||||
 | 
					    fd_set writefds, readfds;
 | 
				
			||||||
 | 
					    char buf[4096];
 | 
				
			||||||
 | 
					    while (num0 || num1 || num2) try { // no end of file in stdin, -out, -err
 | 
				
			||||||
 | 
					      int res(0), s(0);
 | 
				
			||||||
 | 
					      if ((res=waitpid(pid, &s, WNOHANG))) {
 | 
				
			||||||
 | 
					        if (res!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0)
 | 
				
			||||||
 | 
					          throw ExecutionFailedExc("execution failed", *_cmd);
 | 
				
			||||||
 | 
					        _success = true;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // select...
 | 
				
			||||||
 | 
					      FD_ZERO(&writefds);
 | 
				
			||||||
 | 
					      FD_ZERO(&readfds);
 | 
				
			||||||
 | 
					      if (num0) FD_SET(stdIn.ostream(), &writefds);
 | 
				
			||||||
 | 
					      if (num1) FD_SET(stdOut.istream(), &readfds);
 | 
				
			||||||
 | 
					      if (num2) FD_SET(stdErr.istream(), &readfds);
 | 
				
			||||||
 | 
					      timeval tm = {1, 0};
 | 
				
			||||||
 | 
					      int n(mrw::max((num0?stdIn.ostream():0),
 | 
				
			||||||
 | 
					                     mrw::max((num1?stdOut.istream():0),
 | 
				
			||||||
 | 
					                              (num2?stdErr.istream():0))));
 | 
				
			||||||
 | 
					      int num = select(n, &readfds, &writefds, 0, &tm);
 | 
				
			||||||
 | 
					      if (num<0) throw ExecutionFailedExc("select failed", *_cmd);
 | 
				
			||||||
 | 
					      // check and handle stdin
 | 
				
			||||||
 | 
					      if (num0 && num>0
 | 
				
			||||||
 | 
					          && FD_ISSET(stdIn.ostream(), &writefds))
 | 
				
			||||||
 | 
					        if ((num0=write(stdIn.ostream(), in.c_str(), in.size()))>0) {
 | 
				
			||||||
 | 
					          if ((unsigned int)num0<in.size())
 | 
				
			||||||
 | 
					            in = in.substr(num0);
 | 
				
			||||||
 | 
					          else if ((unsigned int)num0==in.size())
 | 
				
			||||||
 | 
					            num0=0, stdIn.close_out();
 | 
				
			||||||
 | 
					        } else if (num0==-1 && (errno!=EINTR&&errno!=EAGAIN))
 | 
				
			||||||
 | 
					          throw ExecutionFailedExc("writing stdin", *_cmd);
 | 
				
			||||||
 | 
					      // check and handle stdout
 | 
				
			||||||
 | 
					      if (num>0 && FD_ISSET(stdOut.istream(), &readfds))
 | 
				
			||||||
 | 
					        if ((num1=read(stdOut.istream(), buf, sizeof(buf)))>0)
 | 
				
			||||||
 | 
					          _res += std::string(buf, num1);
 | 
				
			||||||
 | 
					        else if (num1==-1 && (errno!=EINTR&&errno!=EAGAIN))
 | 
				
			||||||
 | 
					          throw ExecutionFailedExc("readin stdout", *_cmd);
 | 
				
			||||||
 | 
					      // check and handle stderr
 | 
				
			||||||
 | 
					      if (num>0 && FD_ISSET(stdErr.istream(), &readfds))
 | 
				
			||||||
 | 
					        if ((num2=read(stdErr.istream(), buf, sizeof(buf)))>0)
 | 
				
			||||||
 | 
					          _err += std::string(buf, num2);
 | 
				
			||||||
 | 
					        else if (num2==-1 && (errno!=EINTR&&errno!=EAGAIN))
 | 
				
			||||||
 | 
					          throw ExecutionFailedExc("readin stderr", *_cmd);
 | 
				
			||||||
 | 
					    } catch (...) {
 | 
				
			||||||
 | 
					      if (exc) throw;
 | 
				
			||||||
 | 
					      _success = false;
 | 
				
			||||||
 | 
					      return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // wait for child to get return code
 | 
				
			||||||
 | 
					    int s(0);
 | 
				
			||||||
 | 
					    if (waitpid(pid, &s, 0)!=pid || WIFEXITED(s)!=0 && WEXITSTATUS(s)!=0) {
 | 
				
			||||||
 | 
					      if (exc) {
 | 
				
			||||||
 | 
					        throw ExecutionFailedExc("execution failed", *_cmd);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        _success = false;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else { // child
 | 
				
			||||||
 | 
					    stdIn.close_out();
 | 
				
			||||||
 | 
					    stdOut.close_in();
 | 
				
			||||||
 | 
					    stdErr.close_in();
 | 
				
			||||||
 | 
					    stdIn.connect_cin();
 | 
				
			||||||
 | 
					    stdOut.connect_cout(); // if cin is non blocking, child terminates here?!?
 | 
				
			||||||
 | 
					    stdErr.connect_cerr();
 | 
				
			||||||
 | 
					    execvp(_cmd->path(), _cmd->args());
 | 
				
			||||||
 | 
					    exit(1); // execute failed
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  _success = true;
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mrw::Exec& mrw::Exec::operator>>(std::string& res) throw(std::exception) {
 | 
					mrw::Exec& mrw::Exec::operator>>(std::string& res) throw(std::exception) {
 | 
				
			||||||
  execute();
 | 
					  execute();
 | 
				
			||||||
  res += _res;
 | 
					  res += _res;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										110
									
								
								mrw/exec.hpp
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								mrw/exec.hpp
									
									
									
									
									
								
							@@ -9,6 +9,9 @@
 | 
				
			|||||||
    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
					    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $Log$
 | 
					    $Log$
 | 
				
			||||||
 | 
					    Revision 1.5  2004/12/14 20:30:09  marc
 | 
				
			||||||
 | 
					    added possibility to pass string to stdin of child process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Revision 1.4  2004/10/07 09:27:01  marc
 | 
					    Revision 1.4  2004/10/07 09:27:01  marc
 | 
				
			||||||
    errors in documentation
 | 
					    errors in documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,6 +70,18 @@ namespace mrw {
 | 
				
			|||||||
        // you can trace x.what() and x.stacktrace()
 | 
					        // you can trace x.what() and x.stacktrace()
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      @endcode
 | 
					      @endcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      It is also possible to pass an @c stdin input argument to the
 | 
				
			||||||
 | 
					      subprocess called:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @code
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        mrw::Exec cat = mrw::Cmd("/bin/cat")
 | 
				
			||||||
 | 
					          .execute("this is passed to stdin");
 | 
				
			||||||
 | 
					        // "cat" passes all from stdin to stdout, therefore:
 | 
				
			||||||
 | 
					        assert(cat.result()=="this is passed to stdin");
 | 
				
			||||||
 | 
					      } catch (...) {} // ignore
 | 
				
			||||||
 | 
					      @endcode
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
  //@{
 | 
					  //@{
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@@ -99,6 +114,9 @@ namespace mrw {
 | 
				
			|||||||
      and returns the two streams @c cout and @c cerr, also known as @c
 | 
					      and returns the two streams @c cout and @c cerr, also known as @c
 | 
				
			||||||
      stderr and @c stdout.
 | 
					      stderr and @c stdout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      Method @c execute can optionally also take a string parameter
 | 
				
			||||||
 | 
					      that is passed to @c stdin of the child process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      There are different ways of usage for this class. A simple way,
 | 
					      There are different ways of usage for this class. A simple way,
 | 
				
			||||||
      one line of code, to get only the resulting stream (no error)
 | 
					      one line of code, to get only the resulting stream (no error)
 | 
				
			||||||
      is:
 | 
					      is:
 | 
				
			||||||
@@ -146,6 +164,42 @@ namespace mrw {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    Exec& execute(bool exc=true) throw(std::exception);
 | 
					    Exec& execute(bool exc=true) throw(std::exception);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    /** @brief Execute the command, pass @c stdin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @param input Input that is passed to @c stdin of the child process.
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        @param exc
 | 
				
			||||||
 | 
					         - @c true throw an exception if return status is not zero
 | 
				
			||||||
 | 
					         - @c false throw only an exception in case of a fatal error
 | 
				
			||||||
 | 
					         
 | 
				
			||||||
 | 
					        @throw ExecutionFailedExc is thrown if
 | 
				
			||||||
 | 
					         - fork fails
 | 
				
			||||||
 | 
					         - creation or setup of pipes failed
 | 
				
			||||||
 | 
					         - if given parameter is @c true (the default) also if the
 | 
				
			||||||
 | 
					           executed program terminates with an error
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    Exec& execute(const std::string& input, bool exc=true)
 | 
				
			||||||
 | 
					      throw(std::exception);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /** @brief Execute the command, pass @c stdin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @param input Input that is passed to @c stdin of the child process.
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        @param exc
 | 
				
			||||||
 | 
					         - @c true throw an exception if return status is not zero
 | 
				
			||||||
 | 
					         - @c false throw only an exception in case of a fatal error
 | 
				
			||||||
 | 
					         
 | 
				
			||||||
 | 
					        @throw ExecutionFailedExc is thrown if
 | 
				
			||||||
 | 
					         - fork fails
 | 
				
			||||||
 | 
					         - creation or setup of pipes failed
 | 
				
			||||||
 | 
					         - if given parameter is @c true (the default) also if the
 | 
				
			||||||
 | 
					           executed program terminates with an error
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    Exec& execute(char const*const input, bool exc=true)
 | 
				
			||||||
 | 
					      throw(std::exception) {
 | 
				
			||||||
 | 
					      return execute(std::string(input), exc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /** @brief Executes the command if not done, streams @c stdout into a string
 | 
					    /** @brief Executes the command if not done, streams @c stdout into a string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        If the command has not yet been executed successfully, it is
 | 
					        If the command has not yet been executed successfully, it is
 | 
				
			||||||
@@ -220,7 +274,7 @@ namespace mrw {
 | 
				
			|||||||
  /** @brief A system command to be executed
 | 
					  /** @brief A system command to be executed
 | 
				
			||||||
      @pre #include <mrw/exec.hpp>
 | 
					      @pre #include <mrw/exec.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      This class is used in conjunction with mrw::Exec. It mus be
 | 
					      This class is used in conjunction with mrw::Exec. It must be
 | 
				
			||||||
      initialized with the command name, then the command parameters
 | 
					      initialized with the command name, then the command parameters
 | 
				
			||||||
      are appended either with commas, or by streaming them into the
 | 
					      are appended either with commas, or by streaming them into the
 | 
				
			||||||
      command, whatever you like.
 | 
					      command, whatever you like.
 | 
				
			||||||
@@ -284,6 +338,60 @@ namespace mrw {
 | 
				
			|||||||
    */
 | 
					    */
 | 
				
			||||||
    Exec execute(bool exc=true) const throw(std::exception);
 | 
					    Exec execute(bool exc=true) const throw(std::exception);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    /** @brief Create a mrw::Exec and execute the command given an input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Creates a mrw::Exec, executes the command, passes the input
 | 
				
			||||||
 | 
					        and the flag to mrw::Exec::execute() and returns the created
 | 
				
			||||||
 | 
					        mrw::Exec. The result of the execution can be retrieved
 | 
				
			||||||
 | 
					        through the returned mrw::Exec object: The methods
 | 
				
			||||||
 | 
					        mrw::Exec::success(), mrw::Exec::result() and
 | 
				
			||||||
 | 
					        mrw::Exec::error() provide the necessary information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @param input Input that is passed to @c stdin of the child process.
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        @param exc
 | 
				
			||||||
 | 
					         - @c true throw an exception if return status is not zero
 | 
				
			||||||
 | 
					         - @c false throw only an exception in case of a fatal error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @return the mrw::Exec that has executed the command
 | 
				
			||||||
 | 
					         
 | 
				
			||||||
 | 
					        @throw ExecutionFailedExc is thrown if
 | 
				
			||||||
 | 
					         - fork fails
 | 
				
			||||||
 | 
					         - creation or setup of pipes failed
 | 
				
			||||||
 | 
					         - if given parameter is @c true (the default) also if the
 | 
				
			||||||
 | 
					           executed program terminates with an error
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    Exec execute(const std::string& input, bool exc=true) const
 | 
				
			||||||
 | 
					      throw(std::exception);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /** @brief Create a mrw::Exec and execute the command given an input
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Creates a mrw::Exec, executes the command, passes the input
 | 
				
			||||||
 | 
					        and the flag to mrw::Exec::execute() and returns the created
 | 
				
			||||||
 | 
					        mrw::Exec. The result of the execution can be retrieved
 | 
				
			||||||
 | 
					        through the returned mrw::Exec object: The methods
 | 
				
			||||||
 | 
					        mrw::Exec::success(), mrw::Exec::result() and
 | 
				
			||||||
 | 
					        mrw::Exec::error() provide the necessary information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @param input Input that is passed to @c stdin of the child process.
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        @param exc
 | 
				
			||||||
 | 
					         - @c true throw an exception if return status is not zero
 | 
				
			||||||
 | 
					         - @c false throw only an exception in case of a fatal error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @return the mrw::Exec that has executed the command
 | 
				
			||||||
 | 
					         
 | 
				
			||||||
 | 
					        @throw ExecutionFailedExc is thrown if
 | 
				
			||||||
 | 
					         - fork fails
 | 
				
			||||||
 | 
					         - creation or setup of pipes failed
 | 
				
			||||||
 | 
					         - if given parameter is @c true (the default) also if the
 | 
				
			||||||
 | 
					           executed program terminates with an error
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    Exec execute(char const*const input, bool exc=true) const
 | 
				
			||||||
 | 
					      throw(std::exception) {
 | 
				
			||||||
 | 
					      return execute(std::string(input), exc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
    /// Exec is allowed to call @c path() and @c args().
 | 
					    /// Exec is allowed to call @c path() and @c args().
 | 
				
			||||||
    friend class Exec;
 | 
					    friend class Exec;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,9 @@
 | 
				
			|||||||
    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
					    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $Log$
 | 
					    $Log$
 | 
				
			||||||
 | 
					    Revision 1.6  2004/12/14 20:30:10  marc
 | 
				
			||||||
 | 
					    added possibility to pass string to stdin of child process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Revision 1.5  2004/10/13 10:43:11  marc
 | 
					    Revision 1.5  2004/10/13 10:43:11  marc
 | 
				
			||||||
    test for bad exception specification
 | 
					    test for bad exception specification
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,14 +43,20 @@ public:
 | 
				
			|||||||
    std::string res = (mrw::Cmd("/bin/ls"), "-l", "..").execute();
 | 
					    std::string res = (mrw::Cmd("/bin/ls"), "-l", "..").execute();
 | 
				
			||||||
    CPPUNIT_ASSERT(res.find("COPYING")<res.size());
 | 
					    CPPUNIT_ASSERT(res.find("COPYING")<res.size());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  void catTest() {
 | 
				
			||||||
 | 
					    std::string res =mrw::Cmd("/bin/cat").execute("This is a test");
 | 
				
			||||||
 | 
					    CPPUNIT_ASSERT(res=="This is a test");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  void excTest() {
 | 
					  void excTest() {
 | 
				
			||||||
    std::string res = (mrw::Cmd("/bin/false")).execute().result();
 | 
					    std::string res1 = (mrw::Cmd("/bin/false")).execute().result();
 | 
				
			||||||
 | 
					    std::string res2 = (mrw::Cmd("/bin/false")).execute("").result();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void unexpectedExc() throw(std::bad_exception) {
 | 
					  void unexpectedExc() throw(std::bad_exception) {
 | 
				
			||||||
    std::string res = (mrw::Cmd("/bin/false")).execute().result();
 | 
					    std::string res = (mrw::Cmd("/bin/false")).execute().result();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  CPPUNIT_TEST_SUITE(ExecTest);
 | 
					  CPPUNIT_TEST_SUITE(ExecTest);
 | 
				
			||||||
  CPPUNIT_TEST(lsTest);
 | 
					  CPPUNIT_TEST(lsTest);
 | 
				
			||||||
 | 
					  CPPUNIT_TEST(catTest);
 | 
				
			||||||
  CPPUNIT_TEST_EXCEPTION(excTest, mrw::ExecutionFailedExc);
 | 
					  CPPUNIT_TEST_EXCEPTION(excTest, mrw::ExecutionFailedExc);
 | 
				
			||||||
  CPPUNIT_TEST_EXCEPTION(unexpectedExc, std::bad_exception);
 | 
					  CPPUNIT_TEST_EXCEPTION(unexpectedExc, std::bad_exception);
 | 
				
			||||||
  CPPUNIT_TEST_SUITE_END();
 | 
					  CPPUNIT_TEST_SUITE_END();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user