15 #include "pfstreamBuf.h"
18 PipeStreamBuf::PipeStreamBuf(PipeStreamBuf::Direction dir) :
23 #ifndef PHAVE_IOSTREAM
27 assert((dir == Input) || (dir == Output));
29 setg(base(), ebuf(), ebuf());
37 ~PipeStreamBuf(
void) {
45 void PipeStreamBuf::flush(
void) {
48 write_chars(
"", 0,
true);
52 void PipeStreamBuf::command(
const string cmd) {
57 int PipeStreamBuf::overflow(
int c) {
59 assert(_dir == Output);
60 streamsize n = pptr() - pbase();
62 write_chars(pbase(), n,
false);
68 write_chars(&ch, 1,
false);
73 int PipeStreamBuf::sync(
void) {
76 streamsize n = pptr() - pbase();
77 write_chars(pbase(), n,
false);
80 streamsize n = egptr() - gptr();
84 cerr <<
"pfstream tossed out " << n <<
" bytes" << endl;
91 int PipeStreamBuf::underflow(
void) {
92 assert(_dir == Input);
93 if ((eback() == (
char*)0L) || (gptr() == (
char*)0L) ||
94 (egptr() == (
char*)0L)) {
96 char* buf =
new char[4096];
97 char* ebuf = &(buf[4096]);
98 setg(buf, ebuf, ebuf);
100 if (gptr() < egptr()) {
107 #ifdef PHAVE_IOSTREAM
110 size_t len = ebuf() - base();
112 char* buf =
new char[len];
113 size_t n = read_pipe(buf, len);
118 #ifdef PHAVE_IOSTREAM
119 memcpy(eback()+(len-n), buf, n);
121 memcpy(base()+(len-n), buf, n);
129 void PipeStreamBuf::write_chars(
const char* start,
int length,
bool flush) {
130 assert(_dir == Output);
131 size_t orig = _line_buffer.length();
132 string latest(start, length);
138 line = _line_buffer + latest;
142 _line_buffer += latest;
143 size_t eol = _line_buffer.rfind(
'\n', orig);
144 if (eol != string::npos) {
145 line = _line_buffer.substr(0, eol+1);
146 _line_buffer = _line_buffer.substr(eol+1);
150 size_t wrote = write_pipe(line.c_str(), line.length());
152 if (wrote != line.length())
153 cerr <<
"wrote only " << wrote <<
" of " << line.length()
154 <<
" bytes to pipe" << endl;
158 #ifndef WIN_PIPE_CALLS
180 return _pipe != NULL;
191 return (_pipe == NULL) && feof(_pipe);
205 open_pipe(
const string &cmd) {
206 const char *typ = (_dir == Output)?
"w":
"r";
207 _pipe = popen(cmd.c_str(), typ);
208 return (_pipe != NULL);
230 size_t PipeStreamBuf::
231 write_pipe(
const char *data,
size_t len) {
232 size_t wrote_count = fwrite(data, 1, len, _pipe);
244 size_t PipeStreamBuf::
245 read_pipe(
char *data,
size_t len) {
246 return fread(data, 1, len, _pipe);
249 #else // WIN_PIPE_CALLS
278 return (_child_out != 0);
289 return (_child_out == 0);
303 open_pipe(
const string &cmd) {
308 if (_dir == Output) {
314 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
317 HANDLE hChildStdoutRd, hChildStdoutWr;
320 SECURITY_ATTRIBUTES saAttr;
321 saAttr.nLength =
sizeof(SECURITY_ATTRIBUTES);
322 saAttr.bInheritHandle = TRUE;
323 saAttr.lpSecurityDescriptor = NULL;
324 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
326 cerr <<
"Unable to create output pipe\n";
332 if (!SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) {
334 cerr <<
"Unable to redirect stdout\n";
336 CloseHandle(hChildStdoutRd);
337 CloseHandle(hChildStdoutWr);
344 BOOL fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
345 GetCurrentProcess(), &_child_out,
346 0, FALSE, DUPLICATE_SAME_ACCESS);
350 cerr <<
"DuplicateHandle failed\n";
352 CloseHandle(hChildStdoutRd);
353 CloseHandle(hChildStdoutWr);
356 CloseHandle(hChildStdoutRd);
363 char *cmdline =
new char[cmd.length() + 1];
364 strcpy(cmdline, cmd.c_str());
369 if (!WinExec(cmdline, 0)) {
371 cerr <<
"Unable to spawn process.\n";
380 if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
382 cerr <<
"Unable to restore stdout\n";
388 if (!CloseHandle(hChildStdoutWr)) {
390 cerr <<
"Unable to close write end of pipe\n";
394 return (_child_out != 0);
404 if (_child_out != 0) {
405 CloseHandle(_child_out);
416 size_t PipeStreamBuf::
417 write_pipe(
const char *data,
size_t len) {
428 size_t PipeStreamBuf::
429 read_pipe(
char *data,
size_t len) {
430 if (_child_out == 0) {
434 if (!ReadFile(_child_out, data, len, &dwRead, NULL)) {
443 #endif // WIN_PIPE_CALLS