|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
#include <sys/types.h>
|
|
|
#include <sys/wait.h>
|
|
|
#include <sys/wait.h>
|
|
|
#include <signal.h>
|
|
|
#include <signal.h>
|
|
|
|
|
|
#include <sys/select.h>
|
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
#include <cstring>
|
|
|
#include <cerrno>
|
|
|
#include <cerrno>
|
|
|
|
|
|
|
|
|
exitCode = 0;
|
|
|
exitCode = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
|
|
Child::numBytesAvailable() const {
|
|
|
|
|
|
|
|
|
|
|
|
return readStreambuf.numBytesAvailable();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
void
|
|
|
void
|
|
|
Child::run() {
|
|
|
Child::run() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw std::runtime_error("Error creating pipe for stdin: " +
|
|
|
throw std::runtime_error("Error creating pipe for stdin: " +
|
|
|
getErrorText());
|
|
|
getErrorText());
|
|
|
}
|
|
|
}
|
|
|
if (pipe(childStdOutPipe, O_NONBLOCK) != 0) {
|
|
|
|
|
|
|
|
|
if (pipe(childStdOutPipe) != 0) {
|
|
|
close(childStdInPipe[0]);
|
|
|
close(childStdInPipe[0]);
|
|
|
close(childStdInPipe[1]);
|
|
|
close(childStdInPipe[1]);
|
|
|
throw std::runtime_error("Error creating pipe for stdout: " +
|
|
|
throw std::runtime_error("Error creating pipe for stdout: " +
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
|
|
Child::ReadStreambuf::numBytesAvailable() const {
|
|
|
|
|
|
|
|
|
|
|
|
size_t nBytesAvailable = egptr() - gptr();
|
|
|
|
|
|
|
|
|
|
|
|
fd_set readFd;
|
|
|
|
|
|
int retVal;
|
|
|
|
|
|
struct timeval timeout = {0, 0};
|
|
|
|
|
|
|
|
|
|
|
|
FD_ZERO(&readFd);
|
|
|
|
|
|
FD_SET(inputFileDescriptor, &readFd);
|
|
|
|
|
|
|
|
|
|
|
|
// Check if input is available.
|
|
|
|
|
|
retVal = select(inputFileDescriptor + 1, &readFd, NULL, NULL, &timeout);
|
|
|
|
|
|
|
|
|
|
|
|
if (-1 == retVal) {
|
|
|
|
|
|
throw std::runtime_error("Error from select(): " + getErrorText());
|
|
|
|
|
|
} else if (retVal > 0) {
|
|
|
|
|
|
nBytesAvailable++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nBytesAvailable;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
std::streambuf::int_type
|
|
|
std::streambuf::int_type
|
|
|
Child::ReadStreambuf::underflow() {
|
|
|
Child::ReadStreambuf::underflow() {
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "underflow()." << std::endl; // debug
|
|
|
// Check for empty buffer.
|
|
|
// Check for empty buffer.
|
|
|
if (gptr() < egptr()) {
|
|
|
if (gptr() < egptr()) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return traits_type::to_int_type(*gptr());
|
|
|
return traits_type::to_int_type(*gptr());
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "need to fill buffer." << std::endl; // debug
|
|
|
// Need to fill the buffer.
|
|
|
// Need to fill the buffer.
|
|
|
char *base = &(buffer.front());
|
|
|
char *base = &(buffer.front());
|
|
|
char *start = base;
|
|
|
char *start = base;
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
#else
|
|
|
#else
|
|
|
ssize_t nBytesRead;
|
|
|
ssize_t nBytesRead;
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "Requesting read of " << buffer.size() - (start - base)
|
|
|
|
|
|
<< " bytes" << std::endl; // debug
|
|
|
nBytesRead = read(inputFileDescriptor,
|
|
|
nBytesRead = read(inputFileDescriptor,
|
|
|
start,
|
|
|
start,
|
|
|
buffer.size() - (start - base));
|
|
|
buffer.size() - (start - base));
|
|
|
|
|
|
// debug
|
|
|
|
|
|
std::cout << "nBytesRead: " << nBytesRead << std::endl; // debug
|
|
|
|
|
|
for (int i = 0; i < nBytesRead; i++) {
|
|
|
|
|
|
std::cout << (char) start[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
// end of debug
|
|
|
if (-1 == nBytesRead) {
|
|
|
if (-1 == nBytesRead) {
|
|
|
return traits_type::eof();
|
|
|
return traits_type::eof();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
// Update buffer pointers.
|
|
|
// Update buffer pointers.
|
|
|
setg(base, start, start + nBytesRead);
|
|
|
setg(base, start, start + nBytesRead);
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "underflow() return." << std::endl; // debug
|
|
|
|
|
|
|
|
|
return traits_type::to_int_type(*gptr());
|
|
|
return traits_type::to_int_type(*gptr());
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
ssize_t nBytesWritten;
|
|
|
ssize_t nBytesWritten;
|
|
|
|
|
|
|
|
|
nBytesWritten = write(outputFileDescriptor, pbase(), nBytes);
|
|
|
nBytesWritten = write(outputFileDescriptor, pbase(), nBytes);
|
|
|
|
|
|
// debug
|
|
|
|
|
|
std::cout << "flushBuffer(). Requested to write " << nBytes << " bytes, "
|
|
|
|
|
|
<<"wrote " << nBytesWritten << " bytes." << std::endl;
|
|
|
|
|
|
char *ch = pbase();
|
|
|
|
|
|
for (int i = 0; i < nBytesWritten; i++) {
|
|
|
|
|
|
std::cout << (char) ch[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
// end of debug.
|
|
|
|
|
|
|
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
|