On Mon, Aug 19, 2002 at 10:12:34AM +0100, Angus Leeming wrote: > Didn't André post a pipestream class to the list some time ago? These sort of > semantic differences should be encapsulated and hidden away.
I believe there was a strong connection between "my" pipestream class and socket++ (i.e. the pipestream is a cut-down version of the original socket++ with a few tweaks) The problem was that there were doubts on the license of the original code. I try to contact the author but got no response. The original license said: // Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan // // 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 I think this puts us on the safe side, but there was no consensus AFAIR. Andre' PS: I'll attach the stuff in case anybody wants to have a look. -- Those who desire to give up Freedom in order to gain Security, will not have, nor do they deserve, either one. (T. Jefferson)
/* 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(char const * const cmd[]); private: /// unimplemented pipestream(pipestream const &); /// unimplemented void operator=(pipestream const &); }; #endif
// pipestream.h -*- 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 // [EMAIL PROTECTED] #include "pipestream.h" #ifdef WINDOWS #include "klog.h" pipestream::pipestream(char const * const[]) { kmissing(); } #else #include <sys/types.h> #include <sys/socket.h> #include <cstddef> #include <cstdio> #include <unistd.h> #include <errno.h> using std::streambuf; using std::streamsize; 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); /// destructor ~pipebuf(); private: /// no copying to save us ref counting sockets pipebuf(const pipebuf &); /// no assignment pipebuf & operator=(const pipebuf &); /// try to reduce the number of #ifdef in "client code" static int_type end_of_file(); /// static char_type to_char_type(int_type c); /// int_type overflow(int_type c = end_of_file()); /// int_type underflow(); /// streamsize xsputn(char_type const * s, streamsize n); /// bool flush(); /// static int const bufsize_ = 1024; /// get area char_type gbuf_[bufsize_]; /// put area char_type pbuf_[bufsize_]; /// our socket. int const sock_; }; namespace { void error(const char * msg, int exitcode = 0) { if (errno) perror(msg); std::cerr << msg << std::endl; errno = 0; if (exitcode) _exit(exitcode); } pipebuf * pipebuf_create(char const * const 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("socketpair"); return 0; } pid_t pid = vfork(); //pid_t pid = fork(); if (pid == -1) { error("fork"); return 0; } if (pid == 0) { // this is the child if (::close(sockets[1]) == -1) error("child close 1"); if (::dup2(sockets[0], 1) == -1) error("child dup2 1", 10); if (::dup2(sockets[0], 0) == -1) error("child dup2 0", 11); if (::close(sockets[0]) == -1) error("child close 0"); execvp(cmd[0], const_cast<char**>(cmd)); error("execve", 12); } // this is the parent pipebuf * s = new pipebuf(sockets[1]); if (::close(sockets[0]) == -1) error("parent close 0"); return s; } } // end anon namespace 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 } pipebuf::char_type pipebuf::to_char_type(int_type c) { #ifdef MODERN_STL_STREAMS return traits_type::to_char_type(c); #else return static_cast<char_type>(c); #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 true; streamsize n; for (streamsize len = pptr() - pbase(); len > 0; len -= n) { n = ::write(sock_, pbase(), len); if (n == -1) { error("write"); setp(pbase(), pbase() + bufsize_); return false; } } setp(pbase(), pbase() + bufsize_); return true; } pipebuf::int_type pipebuf::underflow() { if (gptr() < egptr()) return gptr() != 0; streamsize n = ::read(sock_, gbuf_, bufsize_); if (n == 0) return end_of_file(); if (n == -1) error("read"); setg(eback(), gbuf_, gbuf_ + n); return gptr() != 0; } 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(to_char_type(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 (end_of_file() == ((*p == '\n') ? overflow(*p) : sputc(*p))) return i; return n; } pipestream::pipestream(char const * const cmd[]) : std::iostream(pipebuf_create(cmd)) {} #endif #ifdef PIPESTREAM_MAIN #include <string> int main() { if (1) { char const * cmd[] = {"maple", "-q", 0}; pipestream ps(cmd); ps << "2^64;\n"; std::string result; ps >> result; std::cout << "res: " << result << "\n"; } if (1) { char const * cmd[] = {"ls", "-la", 0}; pipestream ps(cmd); while (ps) { std::string line; getline(ps, line); std::cout << "res: " << line << "\n"; } } return 0; } #endif // PIPESTREAM_MAIN