| 
				
			 | 
			
			 | 
			@@ -19,6 +19,16 @@ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			// Place, Suite 330, Boston, MA 02111-1307 USA
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			//==============================================================================
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifndef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <unistd.h>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <sys/types.h>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <sys/wait.h>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <signal.h>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <cstring>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <cerrno>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <iostream> // Temporary.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#include <stdexcept>
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -30,22 +40,11 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    readStreambuf(bufSize),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writeStreambuf(bufSize),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    reader(&readStreambuf),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writer(&writeStreambuf) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writer(&writeStreambuf),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmdArgs(args) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    init();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (args.size() == 0) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      //
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else if (args.size() == 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      cmdline = args[0];
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Append all but last command-line arguments.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    for (size_t i = 0; i < args.size() - 1; i++) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      cmdline += args[i] + " ";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmdline += args.back(); // Append last command-line argument.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::Child(std::string childpath, size_t bufSize) :
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -54,6 +53,7 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    reader(&readStreambuf),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writer(&writeStreambuf),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmdline(childpath) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    cmdArgs.push_back(childpath);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    init();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -63,9 +63,15 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::init() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (cmdArgs.empty()) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::invalid_argument("A child executable must be specified.");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    reader.exceptions(std::istream::failbit | std::istream::badbit);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writer.exceptions(std::ostream::failbit | std::ostream::badbit);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childStarted = false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childExited = false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCodeObtainedFlag = false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCode = 0;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -78,6 +84,7 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						     "run() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Set the bInheritHandle flag so pipe handles are inherited. 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    SECURITY_ATTRIBUTES securityAttributes; 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -146,19 +153,33 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    startInfo.hStdInput = childStdInAtChild;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    startInfo.dwFlags |= STARTF_USESTDHANDLES;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Assemble the command line.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string cmdline;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (cmdArgs.size() == 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      cmdline = cmdArgs[0];
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Append all but last command-line arguments.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      for (size_t i = 0; i < cmdArgs.size() - 1; i++) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				cmdline += cmdArgs[i] + " ";
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      cmdline += cmdArgs.back(); // Append last command-line argument.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Create the child process. 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    bool status;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    status = CreateProcess(NULL, 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   (char *) cmdline.c_str(), // command line 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,         	    // process security attributes 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,         	    // primary thread security attributes 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   true,         	    // handles are inherited 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   0,            	    // creation flags 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,         	    // use parent's environment 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,         	    // use parent's current directory 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   &startInfo,   	    // STARTUPINFO pointer 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   &processInfo);	    // receives PROCESS_INFORMATION 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   (char *) cmdline.c_str(),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,          // process security attributes 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,          // primary thread security attributes 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   true,          // handles are inherited 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   0,             // creation flags 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,          // use parent's environment 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   NULL,          // use parent's current directory 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   &startInfo,    // STARTUPINFO pointer 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						   &processInfo); // receives PROCESS_INFORMATION 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // If an error occurs, exit the application. 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!status ) {
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -176,18 +197,121 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childProcess = processInfo.hProcess;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childThread = processInfo.hThread;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childStarted = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Close the child's end of the pipes.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!CloseHandle(childStdOutAtChild)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error closing the child process stdout handle:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error closing the child process "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       "stdout handle:  " + getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			     
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!CloseHandle(childStdInAtChild)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error closing the child process stdin handle:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error closing the child process "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       "stdin handle:  " + getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Create the pipes for the stdin and stdout.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int childStdInPipe[2];
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int childStdOutPipe[2];
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (pipe(childStdInPipe) != 0) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error creating pipe for stdin:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (pipe(childStdOutPipe) != 0) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      close(childStdInPipe[0]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      close(childStdInPipe[1]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error creating pipe for stdout:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Create the child process. 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childPid = fork();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (-1 == childPid) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      for (int i = 0; i < 2; i++) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				close(childStdInPipe[i]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				close(childStdOutPipe[i]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error creating child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (0 == childPid) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // The child executes this.  Redirect stdin.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      if (dup2(childStdInPipe[0], STDIN_FILENO) == -1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				std::string errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Send message to parent.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				errMsg = "Error redirecting stdin in the child:  " + getErrorText();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				write(childStdOutPipe[1], errMsg.data(), errMsg.size());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				exit(-1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Redirect stdout.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      if (dup2(childStdOutPipe[1], STDOUT_FILENO) == -1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				std::string errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Send message to parent.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				errMsg = "Error redirecting stdout in the child:  " + getErrorText();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				write(childStdOutPipe[1], errMsg.data(), errMsg.size());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				exit(-1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Close pipes.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      if ( (close(childStdInPipe[0]) != 0) ||
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				   (close(childStdInPipe[1]) != 0) ||
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				   (close(childStdOutPipe[0]) != 0) ||
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				   (close(childStdOutPipe[1]) != 0) ) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				std::string errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Send message to parent.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				errMsg = "Error closing the pipes in the child:  " + getErrorText();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				write(STDOUT_FILENO, errMsg.data(), errMsg.size());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				exit(-1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Prepare the arguments.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      std::vector<const char *> execvArgv;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      for (auto &arg : cmdArgs) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				execvArgv.push_back(arg.c_str());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      execvArgv.push_back((char *) NULL);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Run the child process image.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      (void) execv(execvArgv[0], (char * const *) &(execvArgv[0]));
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Error from exec.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      std::string errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Send message to parent.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      errMsg = "Error from exec:  " + getErrorText();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      write(STDOUT_FILENO, errMsg.data(), errMsg.size());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      exit(-1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // std::cout << "Child pid:  " << childPid << std::endl; // DEBUG.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Provide the stream buffers with the file descriptors for
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // communicating with the child process.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    readStreambuf.setInputFileDescriptor(childStdOutPipe[0]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    writeStreambuf.setOutputFileDescriptor(childStdInPipe[1]);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Close the child's end of the pipes.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if ( (close(childStdInPipe[0]) != 0) ||
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				 (close(childStdOutPipe[1]) != 0) ) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      std::string errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error closing child's end of pipes in "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       "the parent:  " + getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childStarted = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -200,107 +324,144 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!TerminateProcess(childProcess, terminateExitCode)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::runtime_error("Error terminating the child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (kill(childPid, SIGTERM) != 0) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error terminating the child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    bool
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::isDone() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  bool
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::isDone() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (exitCodeObtainedFlag) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (childExited) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!childStarted) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::logic_error("Child process was not started "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      "when isDone() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::logic_error("Child process was not started "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						     "when isDone() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int result;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!GetExitCodeProcess(childProcess, (LPDWORD) &result)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::runtime_error("Error checking status of child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error checking status of child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (STILL_ACTIVE == result) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Child process has exited.  Save the exit code.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCode = result;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCodeObtainedFlag = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int status = 0;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    result = waitpid(childPid, &status, WNOHANG);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // std::cout << "isDone().  waitpid(" << childPid << ",...) returned " << result << std::endl; // DEBUG
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (-1 == result) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error checking status of child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else if (0 == result) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Child is still running.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // std::cout << "isDone().  Child is still running..." << std::endl; // DEBUG.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return false;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // std::cout << "isDone().  Child exited." << std::endl; // DEBUG.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (WIFEXITED(status)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Child exited normally.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      exitCode = WEXITSTATUS(status);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      exitCodeObtainedFlag = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      //std::cout << "isDone().  Child exited normally.  Exit code:  " << exitCode << std::endl; // DEBUG.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    childExited = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int32_t
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::result() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  int32_t
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::result() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (exitCodeObtainedFlag) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return exitCode;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return exitCode;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!childStarted) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::logic_error("Child process was not started "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      "when result() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check whether the process is running, and get the exit code.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!isDone()) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::logic_error("Child process was still running"
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						     "when result() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int result;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Child process has exited.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!exitCodeObtainedFlag) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!GetExitCodeProcess(childProcess, (LPDWORD) &result)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::runtime_error("Error getting child process exit code:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Exit code is not available.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Child process has exited but the exit "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       "code is not available");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Error if the process has not exited.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (STILL_ACTIVE == result) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::logic_error("Child process was active when "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      "result() was called");
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Child process has exited.  Save the exit code.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCode = result;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    exitCodeObtainedFlag = true;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return exitCode;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return result;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::getErrorText() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  std::string
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::getErrorText() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    LPVOID winMsgBuf;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    DWORD lastError = GetLastError(); 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    FormatMessage(
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    FORMAT_MESSAGE_ALLOCATE_BUFFER | 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      FORMAT_MESSAGE_FROM_SYSTEM |
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      NULL,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      lastError,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      (char *) &winMsgBuf,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      0, NULL );
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  FORMAT_MESSAGE_ALLOCATE_BUFFER | 
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  FORMAT_MESSAGE_FROM_SYSTEM |
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  NULL,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  lastError,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  (char *) &winMsgBuf,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  0, NULL );
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::string errMsg((char *) winMsgBuf);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    LocalFree(winMsgBuf);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return errMsg;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return strerror(errno);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    Child::ReadStreambuf::ReadStreambuf(std::size_t bufferSize) :
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      inputHandle(0),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      buffer(bufferSize + 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::ReadStreambuf::ReadStreambuf(std::size_t bufferSize) :
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    inputHandle(0),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    inputFileDescriptor(-1),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    buffer(bufferSize + 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    char *end = &(buffer.front()) + buffer.size();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -309,23 +470,32 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::ReadStreambuf::setInputHandle(HANDLE inHandle) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::ReadStreambuf::setInputHandle(HANDLE inHandle) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    inputHandle = inHandle;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::ReadStreambuf::setInputFileDescriptor(int inFd) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    inputFileDescriptor = inFd;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::streambuf::int_type
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::ReadStreambuf::underflow() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  std::streambuf::int_type
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::ReadStreambuf::underflow() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check for empty buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (gptr() < egptr()) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Not empty.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return traits_type::to_int_type(*gptr());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Not empty.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return traits_type::to_int_type(*gptr());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Need to fill the buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    char *base = &(buffer.front());
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -334,26 +504,37 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check whether this is the first fill.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (eback() == base) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Not the first fill.  Copy one putback character.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    *(eback()) = *(egptr() - 1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    start++;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Not the first fill.  Copy one putback character.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      *(eback()) = *(egptr() - 1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      start++;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // start points to the start of the buffer.  Fill buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    DWORD nBytesRead;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!ReadFile(inputHandle,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      start,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      buffer.size() - (start - base),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      &nBytesRead,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      NULL)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  start,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  buffer.size() - (start - base),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  &nBytesRead,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					  NULL)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    size_t nBytesRead;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    nBytesRead = read(inputFileDescriptor,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					      start,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					      buffer.size() - (start - base));
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (-1 == nBytesRead) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check for EOF.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (0 == nBytesRead) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Update buffer pointers.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    setg(base, start, start + nBytesRead);
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -362,9 +543,13 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    Child::WriteStreambuf::WriteStreambuf(std::size_t bufferSize) :
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      outputHandle(0),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      buffer(bufferSize + 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::WriteStreambuf(std::size_t bufferSize) :
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    outputHandle(0),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    outputFileDescriptor(-1),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    buffer(bufferSize + 1) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    char *base = &(buffer.front());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -373,64 +558,84 @@ namespace CodeDweller { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::WriteStreambuf::setOutputHandle(HANDLE outHandle) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::setOutputHandle(HANDLE outHandle) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    outputHandle = outHandle;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::setOutputFileDescriptor(int outFd) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    outputFileDescriptor = outFd;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::WriteStreambuf::flushBuffer() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  void
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::flushBuffer() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Write.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::ptrdiff_t nBytes = pptr() - pbase();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#ifdef WIN32
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    DWORD nBytesWritten;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (!WriteFile(outputHandle,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      pbase(),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      nBytes,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      &nBytesWritten,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      NULL)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    pbump(epptr() - pptr()); // Indicate failure.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::runtime_error("Error writing to child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (nBytes != nBytesWritten) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    pbump(epptr() - pptr()); // Indicate failure.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    throw std::runtime_error("Not all data was written to to child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					   pbase(),
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					   nBytes,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					   &nBytesWritten,
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					   NULL)) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Clear the output buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      pbump(-nBytes);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Error writing to child process:  " +
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#else
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    size_t nBytesWritten;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    nBytesWritten = write(outputFileDescriptor, pbase(), nBytes);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#endif
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Clear the output buffer.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    pbump(-nBytes);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (nBytes != nBytesWritten) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      throw std::runtime_error("Not all data was written to to child "
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						       "process:  " + getErrorText());
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    std::streambuf::int_type
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::WriteStreambuf::overflow(int_type ch) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  std::streambuf::int_type
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::overflow(int_type ch) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Check whether we're writing EOF.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (traits_type::eof() != ch) {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Not writing EOF.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    *(pptr()) = ch;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    pbump(1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Not writing EOF.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      *(pptr()) = ch;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      pbump(1);
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Write.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    flushBuffer();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Write.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      flushBuffer();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    // Success.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return ch;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      // Success.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      return ch;
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return traits_type::eof();
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  }
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      Child::WriteStreambuf::sync() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  int
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			  Child::WriteStreambuf::sync() {
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    flushBuffer(); // Throws exception on failure.
 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
 |