1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/***************************************************************
* This file defines a class UnnamedPipe whose sole purpose
* in life is to create ... an unnamed pipe, of course. It is
* Unix specific, relying on the "pipe" system call.
*
* The key member functions are in() and out(), which are
* somewhat confusingly named! in() returns the istream
* associated with the pipe and out() returns the ostream
* associated with the pipe. That means you use out() to write
* things to the pipe and in() to read things from the pipe.
*
***************************************************************/
#ifndef _UNNAMEDPIPE_
#define _UNNAMEDPIPE_
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <streambuf>
using namespace std;
/**************************************************
See "The C++ Standard Library", by Nicolai M. Josuttis
Chapter 13 for info on how fd(in|out)(buff|stream)
works. This code is based on that stuff.
**************************************************/
class fdoutbuff : public streambuf
{
public:
int fileDes;
fdoutbuff(int fd) { fileDes = fd; }
int_type overflow(int c) {
char cp = c;
return (c == EOF || write(fileDes,&cp,1) != 1) ? EOF : c;
}
streamsize xsputn (const char* s, streamsize n) { return write(fileDes,s,n); }
};
class fdostream : public ostream
{
public:
fdoutbuff buff;
fdostream(int fd) : buff(fd), ostream(&buff) { }
};
static const int unpbuffSize = 10;
static const int unpextra = 4;
class fdinbuff : public streambuf
{
public:
char buff[unpbuffSize];
int fileDes;
fdinbuff(int fd) { fileDes = fd; char *tmp = buff+unpextra; setg(tmp,tmp,tmp); }
int_type underflow()
{
if (gptr() >= egptr())
{
int leftover = min((long int)unpextra, (long int)(gptr() - eback())), readSize;
memmove(buff + (unpextra-leftover), gptr() - leftover, leftover);
if ((readSize=read(fileDes, buff + unpextra, unpbuffSize - unpextra)) <= 0) return EOF;
setg(buff + (unpextra-leftover), buff + unpextra, buff + (4+readSize));
}
return *gptr();
}
};
class fdistream : public istream
{
public:
fdinbuff buff;
fdistream(int fd) : buff(fd), istream(&buff) { }
};
/***************************************************************
* UnnamedPipe
***************************************************************/
class UnnamedPipe
{
public:
fdostream *_out;
fdistream *_in;
int fd[2];
bool openmask[2];
UnnamedPipe()
{
if (pipe(fd) == -1) { perror("Failed to create pipe!"); exit(1); }
openmask[0] = openmask[1] = true;
_in = 0;
_out = 0;
}
~UnnamedPipe() {
if (_in) {
delete _in;
}
if (openmask[0]) {
close(fd[0]);
}
if (_out) {
delete _out;
}
if (openmask[1]) {
close(fd[1]);
}
}
fdistream& in() { if (!_in) _in = new fdistream(fd[0]); return *_in; }
fdostream& out() { if (!_out) _out = new fdostream(fd[1]); return *_out; }
int fdin() { return fd[0]; }
int fdout() { return fd[1]; }
int setStdinToPipe() { return dup2(fdin(),fileno(stdin)); }
int setStdoutToPipe() { return dup2(fdout(),fileno(stdout)); }
int setStderrToPipe() { return dup2(fdout(),fileno(stderr)); }
void closeIn() {
if (_in) { delete _in; _in = 0; }
if (openmask[0]) { close(fd[0]); openmask[0] = false; }
}
void closeOut() {
// const char ts[2] = {EOF,'\n'};
if (_out) { delete _out; _out = 0; }
if (openmask[1]) {
// write(fd[1],ts,2);
close(fd[1]);
openmask[1] = false; }
}
};
#endif
|