Could people with compiler != g++ 2.95 please try the attached version?
Andre' -- André Pönitz .............................................. [EMAIL PROTECTED]
/* This file is part of * ====================================================== * * LyX, The Document Processor * * Copyright 2001 The LyX Team. * * ====================================================== */ #ifndef PIPESTREAM_H #define PIPESTREAM_H #include <iostream> class pipestream : public std::iostream { public: /// constructor taking the external command as argument explicit pipestream(const char * cmd); private: /// unimplemented pipestream(pipestream const &); /// unimplemented void operator=(pipestream const &); }; #endif
// pipestream.C -*- C++ -*- socket library // Copyright(C) 1992,1993,1994 Gnanasekaran Swaminathan <[EMAIL PROTECTED]> // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright // notice and this paragraph are preserved on all copies. // This software is provided "as is" with no express or implied warranty. // // Version: 17Oct95 1.10 // You can simultaneously read and write into a pipebuf just like you // can listen and talk through a telephone. Hence, the read and the write // buffers are different. That is, they do not share the same memory. // // Read: gptr() points to the start of the get area. The unread chars are // gptr() - egptr(). base() points to the read buffer // // eback() is set to base() so that pbackfail() is called only when there // is no place to putback a char. And pbackfail() always returns EOF. // // Write: pptr() points to the start of the put area The unflushed chars // are pbase() - pptr() pbase() points to the write buffer. epptr() // points to the end of the write buffer. // // Output is flushed whenever one of the following conditions holds: (1) // pptr() == epptr() (2) EOF is written (3) linebuffered and '\n' is // written // // Unbuffered: Input buffer size is assumed to be of size 1 and output // buffer is of size 0. That is, egptr() <= base()+1 and epptr() == // pbase(). #include <sys/types.h> #include <sys/socket.h> #include <cstddef> #include <cstdio> #include <unistd.h> #include <errno.h> #include "pipestream.h" using std::streambuf; using std::streamsize; namespace { void error(const char * msg) { if (errno) perror(msg); std::cerr << msg << std::endl; errno = 0; } } class pipebuf : public streambuf { public: #ifndef MODERN_STL_STREAMS typedef char char_type; typedef int int_type; #endif public: /// The only constructor we need explicit pipebuf(int sock); /// no copying to save us ref counting sockets pipebuf(const pipebuf &); /// no assignment pipebuf & operator=(const pipebuf &); /// destructor ~pipebuf(); /// streamsize xsputn(char_type const * s, streamsize n); private: /// try to reduce the number of #ifdef in "client code" static int_type end_of_file(); /// int_type overflow(int_type c = end_of_file()); /// int_type underflow(); /// bool flush(); /// /// static int const bufsize_ = 2; /// get area char_type gbuf_[bufsize_]; /// put area char_type pbuf_[bufsize_]; /// our socket. int const sock_; }; pipebuf::pipebuf(int sock) : sock_(sock) { setg(gbuf_, gbuf_, gbuf_); setp(pbuf_, pbuf_ + bufsize_); } pipebuf::~pipebuf() { overflow(); ::close(sock_); } pipebuf::int_type pipebuf::end_of_file() { #ifdef MODERN_STL_STREAMS return traits_type::eof(); #else return EOF; #endif } // return true when there is nothing to flush or when the flush is a success // return false when it could not flush bool pipebuf::flush() { if (pptr() == pbase()) return false; streamsize len = pptr() - pbase(); streamsize rlen = len; streamsize wlen = 0; while (rlen > 0) { streamsize wval = ::write(sock_, pbase(), rlen); if (wval == -1) { error("pipebuf::write"); break; } rlen -= wval; wlen += wval; } setp(pbase(), pbase() + bufsize_); return len == wlen; } pipebuf::int_type pipebuf::underflow() { if (gptr() < egptr()) return gptr() != 0; int_type rval = ::read(sock_, gbuf_, bufsize_); if (rval == -1) error("pipebuf::read"); if (rval == 0) return end_of_file(); setg(eback(), gbuf_, gbuf_ + rval); return gptr() != 0; } // if c == EOF, return flush(); // if c == '\n' and linebuffered, insert c and // return (flush() == EOF) ? EOF : c; // otherwise insert c into the buffer and return c pipebuf::int_type pipebuf::overflow(int_type c) { if (c == end_of_file()) return flush() ? 0 : c; if (pptr() >= epptr()) if (!flush()) return end_of_file(); sputc(c); if (c == '\n' || pptr() >= epptr()) if (!flush()) return end_of_file(); return c; } streamsize pipebuf::xsputn(char_type const * p, streamsize n) { if (n <= 0) return 0; for (streamsize i = 0; i < n; i++, p++) { if (*p == '\n') { if (overflow(*p) == end_of_file()) return i; } else if (sputc(*p) == end_of_file()) return i; } return n; } ///////////////////////////////////////////////////////////////// extern char** environ; namespace { pipebuf * create(const char * cmd) { // child closes sockets[1] and uses sockets[0] // parent closes sockets[0] and uses sockets[1] int sockets[2]; if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { error("pipestream: socketpair"); return 0; } pid_t pid = vfork(); //pid_t pid = fork(); if (pid == -1) { error("pipestream: fork"); return 0; } if (pid == 0) { // child process if (::close(sockets[1]) == -1) error("pipestream: child close 1"); if (::dup2(sockets[0], 1) == -1) { error("pipestream: child dup2 1"); _exit(0x70); } if (::dup2(sockets[0], 0) == -1) { error("pipestream: child dup2 0"); _exit(0x71); } if (::close(sockets[0]) == -1) error("pipestream: child close 0"); const char * argv[4]; argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = cmd; argv[3] = 0; execve("/bin/sh", const_cast<char**>(argv), environ); error("pipestream: execve"); _exit(0x7f); } // parent process pipebuf * s = new pipebuf(sockets[1]); if (::close(sockets[0]) == -1) error("pipestream: parent close 0"); return s; } } // end anon namespace pipestream::pipestream(const char * cmd) : ios(create(cmd)) {} #ifdef PIPESTREAM_MAIN #include <string> int main() { if (1) { pipestream ps("maple -q"); ps << "2^64;\n"; std::string result; ps >> result; std::cout << "res: " << result << "\n"; } if (0) { pipestream ps("ls -la"); while (ps) { std::string line; getline(ps, line); std::cout << "res: " << line << "\n"; } } return 0; } #endif // PIPESTREAM_MAIN