# # patch "Makefile.am" # from [594039be90d24ac4ad583f281a211e68f6eb98e8] # to [8238f65aa9e2dfdc823d6048cbfab48b3a220bc8] # # patch "netxx_pipe.cc" # from [b240094ad56b06c79b67a17cfd0f09947f127043] # to [00fa9adcc4bb374d47b62ac87d8b9470deb2dc87] # # patch "netxx_pipe.hh" # from [40b953e9eb7c750cda3b8d7241e895900c776aa5] # to [35de847785e98f5fbdbd05d16f82d7cc9e8c030b] # # patch "unit_tests.cc" # from [6fb3ef8ee1b90b9b4eb40217938d637cd515d401] # to [acf9762e5f7fee02c6383d543540d5143464ad08] # # patch "unit_tests.hh" # from [7213d23add3f0715300ca0348d9c16b1d136cc3e] # to [6fc232dc37455c348f52016b1e6c4831ced1399d] # =============================================== --- Makefile.am 594039be90d24ac4ad583f281a211e68f6eb98e8 +++ Makefile.am 8238f65aa9e2dfdc823d6048cbfab48b3a220bc8 @@ -47,7 +47,8 @@ cycle_detector.hh randomfile.hh adler32.hh quick_alloc.hh \ netio.hh smap.hh gettext.h \ package_revision.c package_revision.h \ - package_full_revision.c package_full_revision.h options.hh + package_full_revision.c package_full_revision.h options.hh \ + netxx_pipe.cc NETXX_SOURCES = \ netxx/accept.cxx netxx/accept.h netxx/address.cxx \ @@ -62,7 +63,7 @@ netxx/address.h netxx/datagram.h netxx/datagramserver.h \ netxx/netbuf.h netxx/netxx.h netxx/peer.h netxx/probe.h \ netxx/probeinfo.h netxx/sockopt.h netxx/stream.h netxx/streambase.h \ - netxx/streamserver.h netxx/timeout.h netxx/types.h netxx_pipe.cc + netxx/streamserver.h netxx/timeout.h netxx/types.h CRYPTOPP_SOURCES = \ =============================================== --- netxx_pipe.cc b240094ad56b06c79b67a17cfd0f09947f127043 +++ netxx_pipe.cc 00fa9adcc4bb374d47b62ac87d8b9470deb2dc87 @@ -5,13 +5,84 @@ // see the file COPYING for details #include +#include "sanity.hh" Netxx::PipeStream::PipeStream(int _readfd, int _writefd) - : readfd(_readfd), writefd(_writefd) + : readfd(_readfd), writefd(_writefd), child() { pi_.add_socket(readfd); pi_.add_socket(writefd); } +#ifndef __WIN32__ +#include +#include +#include +#include + +// copied from netsync.cc from the ssh branch +static pid_t pipe_and_fork(int *fd1,int *fd2) +{ pid_t result=-1; + fd1[0]=-1; fd1[1]=-1; + fd2[0]=-1; fd2[1]=-1; + if (pipe(fd1)) return -1; + if (pipe(fd2)) + { close(fd1[0]); close(fd1[1]); return -1; } + result=fork(); + if (result<0) + { close(fd1[0]); close(fd1[1]); + close(fd2[0]); close(fd2[1]); + return -1; + } + else if (!result) + { // fd1[1] for writing, fd2[0] for reading + close(fd1[0]); + close(fd2[1]); + if (dup2(fd2[0],0)!=0 || dup2(fd1[1],1)!=1) + { perror("dup2"); + exit(-1); // kill the useless child + } + close(fd1[1]); + close(fd2[0]); + } + else + { // fd1[0] for reading, fd2[1] for writing + close(fd1[1]); + close(fd2[0]); + } + return result; +} +#endif + +Netxx::PipeStream::PipeStream (const std::string &cmd, const std::vector &args) + : readfd(), writefd(), child() +{ +#ifdef WIN32 +#else + int fd1[2],fd2[2]; + child=pipe_and_fork(fd1,fd2); + if (child<0) + { throw oops("pipe/fork failed "+std::string(strerror(errno))); + } + else if (!child) + { const unsigned newsize=64; + const char *newargv[newsize]; + unsigned newargc=0; + newargv[newargc++]=cmd.c_str(); + for (std::vector::const_iterator i=args.begin();i!=args.end();++i) + newargv[newargc++]=cmd.c_str(); + newargv[newargc]=0; + execvp(newargv[0],const_cast(newargv)); + perror(newargv[0]); + exit(errno); + } + readfd=fd1[0]; + writefd=fd2[1]; + fcntl(readfd,F_SETFL,fcntl(readfd,F_GETFL)|O_NONBLOCK); +#endif + pi_.add_socket(readfd); + pi_.add_socket(writefd); +} + Netxx::signed_size_type Netxx::PipeStream::read (void *buffer, size_type length) { return ::read(readfd,buffer,length); } @@ -23,6 +94,11 @@ void Netxx::PipeStream::close (void) { ::close(readfd); ::close(writefd); +// wait for Process to end (before???) +#ifdef WIN32 +#else + if (child) waitpid(child,0,0); +#endif } Netxx::socket_type Netxx::PipeStream::get_socketfd (void) const @@ -42,3 +118,37 @@ const Netxx::ProbeInfo* Netxx::PipeStream::get_probe_info (void) const { return &pi_; } + +#ifdef BUILD_UNIT_TESTS +#include "unit_tests.hh" + +static void +simple_pipe_test() +{ std::vector args; +#ifdef WIN32 + args.push_back("\\"); + Netxx::PipeStream pipe("dir",args); +#else + args.push_back("/"); + Netxx::PipeStream pipe("ls",args); +#endif + std::string result; + char buf[1024]; + Netxx::signed_size_type bytes; + do + { bytes=pipe.read(buf,sizeof buf); + if (bytes<=0) break; + result+=std::string(buf,bytes); + } while (true); + pipe.close(); + BOOST_CHECK(!result.empty()); + L(F("command output is: %s\n") % result); +} + +void +add_pipe_tests(test_suite * suite) +{ + I(suite); + suite->add(BOOST_TEST_CASE(&simple_pipe_test)); +} +#endif =============================================== --- netxx_pipe.hh 40b953e9eb7c750cda3b8d7241e895900c776aa5 +++ netxx_pipe.hh 35de847785e98f5fbdbd05d16f82d7cc9e8c030b @@ -1,9 +1,11 @@ // -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- // copyright (C) 2005 Christof Petig // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details +#include +#include #include #include @@ -12,9 +14,10 @@ class PipeStream : public StreamBase { int readfd, writefd; ProbeInfo pi_; + int child; public: explicit PipeStream (int readfd, int writefd); -// explicit PipeStream (const std::string &cmd, const std::vector &args); + explicit PipeStream (const std::string &cmd, const std::vector &args); virtual signed_size_type read (void *buffer, size_type length); virtual signed_size_type write (const void *buffer, size_type length); virtual void close (void); =============================================== --- unit_tests.cc 6fb3ef8ee1b90b9b4eb40217938d637cd515d401 +++ unit_tests.cc acf9762e5f7fee02c6383d543540d5143464ad08 @@ -78,6 +78,9 @@ if (t.empty() || t.find("crypto") != t.end()) add_crypto_tests(suite); + if (t.empty() || t.find("pipe") != t.end()) + add_pipe_tests(suite); + // all done, add our clean-shutdown-indicator suite->add(BOOST_TEST_CASE(&clean_shutdown_dummy_test)); =============================================== --- unit_tests.hh 7213d23add3f0715300ca0348d9c16b1d136cc3e +++ unit_tests.hh 6fc232dc37455c348f52016b1e6c4831ced1399d @@ -34,5 +34,6 @@ void add_path_component_tests(test_suite * suite); void add_globish_tests(test_suite * suite); void add_crypto_tests(test_suite * suite); +void add_pipe_tests(test_suite * suite); #endif