C++ pipes

C++ pipes

Post by Reinhard Nadrcha » Wed, 09 Jan 2002 15:55:52



In order to wrap some complex shell program into C++ classes and/or
functions I need to do the following:

1. Creating/Manipulating some input data stream
2. Piping this stream to the program (as it's stdin)
3. Processing the output (i.e. parsing stdout into a struct/class

The * way to do this would be to write the input data of the program
in some (temporary) file, using system() or popen() and parsing the
output file. This would imply to create at least one temporary file.

A second posibility would be to use the GNU C++ Iostream Library's
procbuf class. To my experience this works for either the input stream
or the output stream, but not both of them.

Is there any solution (preferably using iostream/ostream-like classes
and C++ streambuffers) to this problem?

Thanks in advance,
Reinhard

 
 
 

C++ pipes

Post by Jim Patterso » Thu, 10 Jan 2002 12:01:35



> In order to wrap some complex shell program into C++ classes and/or
> functions I need to do the following:

> 1. Creating/Manipulating some input data stream
> 2. Piping this stream to the program (as it's stdin)
> 3. Processing the output (i.e. parsing stdout into a struct/class

> The * way to do this would be to write the input data of the program
> in some (temporary) file, using system() or popen() and parsing the
> output file. This would imply to create at least one temporary file.

> A second posibility would be to use the GNU C++ Iostream Library's
> procbuf class. To my experience this works for either the input stream
> or the output stream, but not both of them.

I haven't used procbuf, but it appears to be just a C++ variation of
popen which does have that restriction.

Quote:> Is there any solution (preferably using iostream/ostream-like classes
> and C++ streambuffers) to this problem?

It's easy enough to set up pipes yourself using the pipe function. You
then just need to use dup/dup2 to map them onto cin/cout, fork the
subprocess, and then use dup2 to put things back again. That is all C
code, of course, but you can drop back into C++ once the subprocess is
set up.

Something like this should work. I'll leave it to you to test it (and
put in some error checking).

    int infd[2], outfd[2];
    pipe(infd); pipe(outfd);
    int savein = dup(0), saveout=dup(1);
    dup2(infd[0], 0); close(infd[0]);
    dup2(outfd[1], 1); close(outfd[1]);
    int pid = fork();
    if (pid==0) {
       close(infd[1]);
       close(outfd[0]);
       close(savein);
       close(saveout);
       execl(...);
    } else {
       dup2(savein, 0); close(savein);
       dup2(saveout, 1); close(saveout);
    }
    ifstream readProc(outfd[0]);
    ofstream writeProc(infd[1]);

At this point, readProc and writeProc should be C++ streams mapping from
and to the subprocess.

This is all somewhat system specific. It is likely POSIX compliant, or
nearly so, but will need some tweaking to build on Windows.
--
Jim Patterson
Ottawa, Ont
CANADA

 
 
 

C++ pipes

Post by Emil + Dawn Paquett » Sat, 12 Jan 2002 15:53:29



> In order to wrap some complex shell program into C++ classes and/or
> functions I need to do the following:

> 1. Creating/Manipulating some input data stream
> 2. Piping this stream to the program (as it's stdin)
> 3. Processing the output (i.e. parsing stdout into a struct/class

> The * way to do this would be to write the input data of the program
> in some (temporary) file, using system() or popen() and parsing the
> output file. This would imply to create at least one temporary file.

> A second posibility would be to use the GNU C++ Iostream Library's
> procbuf class. To my experience this works for either the input stream
> or the output stream, but not both of them.

> Is there any solution (preferably using iostream/ostream-like classes
> and C++ streambuffers) to this problem?

> Thanks in advance,
> Reinhard

It should be possible to define your own target for the standard out-object.

i think it would look like this:

template<class charT, class Traits>
basic_istream<charT, Traits>& operator >>
 (basic_istream<charT, Traits >& is, UserDefinedType& x)
{
ios_base::iostate err = 0;

try {

 typename basic_istream<charT, Traits>::sentry ipfx(is);

 if(ipfx)
 {
  // Do whatever has to be done!
  // Typically you will access the stream's locale or buffer.
  // Don't call stream member functions here in MT environments!
  // Add state bits to the err variable if necessary, e.g.

  // if (...) err |= ios_base::failbit;
 }

Quote:} // try

catch(...)                                                   //1
{
   bool flag = FALSE;
   try { is.setstate(ios_base::failbit); }                   //2
   catch( ios_base::failure ) { flag= TRUE; }                //3
   if ( flag ) throw;                                        //4

Quote:}

if ( err ) is.setstate(err);                                 //5

return is;

Quote:}

Similarly, the pattern for the inserter looks like this:

template<class charT, class Traits>
basic_ostream<charT, Traits>& operator <<
(basic_ostream<charT, Traits >& os, const UserDefinedType& x)
{
ios_base::iostate err = 0;

try {
 typename basic_ostream<charT, Traits>::sentry opfx(os);

 if(opfx)
 {
  // Do whatever has to be done!
  // Typically you will access the stream's locale or buffer.
  // Don't call stream member functions here in MT environments!
  // Add state bits to the err variable if necessary, e.g.

  // if (...) err |= ios_base::failbit;
  // Reset the field width after usage, i.e.
  // os.width(0);
 }

Quote:} //try

catch(...)
{
   bool flag = FALSE;
   try { os.setstate(ios_base::failbit); }
   catch( ios_base::failure ) { flag= TRUE; }
   if ( flag ) throw;

Quote:}

if ( err ) os.setstate(err);

return os;

Quote:}

Greetings,
Stefan Depenbrock
 
 
 

1. dump pipe gzip pipe ssh pipe dd... blocksize?

Here's the command I'm planning to use for dumping across a network:

dump -0u -B 8000000 -f - /dev/sd0a | gzip | ssh host 'dd obs=32k of=/dev/nrst0'

Notice I define a blocksize on the dd command, but I haven't defined one
anywhere else. This was after a write failuer with no block size set on a
big backup. Someone suggested setting the block size miught help. I'm not
too sure what the ramifications of this are. Is it a Bad Thing to mix the
block size? I don't believe gzip gives you an option for setting block
size. Should I worry? A couple of test backups and retores seemed to work
okay.

Thanks,
jon

2. Extracting documentation from C code.

3. How do I use Named Pipes in Unix C++

4. Problems with the AMD K6?

5. open pipe use C++

6. newbie: read configuration file

7. Using c++ ifstream with named pipe

8. Writers Seeking Publication

9. How do I use Named Pipes in Unix C++?

10. How do I use Named Pipes in Unix C++

11. c/c++ send()ing fails, errno says "broken pipe"

12. C++ sockets on unix, problems with broken pipe

13. Named Pipes in C++