$OpenBSD: patch-lib_subprocess_hpp,v 1.1.1.1 2019/03/14 14:47:07 stsp Exp $
Get rid of GNU-specific C++ type.
Trim down to features actually needed by Textsuggest.
Index: lib/subprocess.hpp
--- lib/subprocess.hpp.orig
+++ lib/subprocess.hpp
@@ -11,7 +11,7 @@
 #include <string>
 #include <vector>
 #include <iostream>
-#include <ext/stdio_filebuf.h>
+#include <sstream>
 #include <cstdio>
 #include <system_error>
 
@@ -27,71 +27,66 @@ class popen
 public:
 
     popen(const std::string& cmd, std::vector<std::string> argv)
-        : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr)
     {
-        if (pipe(in_pipe)  == -1 ||
-            pipe(out_pipe) == -1 ||
-            pipe(err_pipe) == -1 )
-        {
-            throw std::system_error(errno, std::system_category());
-        }
-
+        out_stream = new std::stringstream;
+        err_stream = new std::stringstream;
+        open_pipes();
         run(cmd, argv);
     }
 
-    popen(const std::string& cmd, std::vector<std::string> argv, std::ostream& pipe_stdout)
-        : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr)
-    {
-        auto filebuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(pipe_stdout.rdbuf());
-        out_pipe[READ]  = -1;
-        out_pipe[WRITE] = filebuf->fd();
-
-        if (pipe(in_pipe) == -1 ||
-            pipe(err_pipe) == -1 )
-        {
-            throw std::system_error(errno, std::system_category());
-        }
-
-        run(cmd, argv);
-    }
-
     ~popen()
     {
-        delete in_filebuf;
-        delete in_stream;
-        if (out_filebuf != nullptr) delete out_filebuf;
-        if (out_stream  != nullptr) delete out_stream;
-        delete err_filebuf;
+        close_pipe(in_pipe);
+        close_pipe(err_pipe);
+        close_pipe(out_pipe);
+        delete out_stream;
         delete err_stream;
     }
 
-    std::ostream& stdin()  { return *in_stream;  };
+    std::istream& get_stdout() { return *out_stream; };
+    std::istream& get_stderr() { return *err_stream; };
 
-    std::istream& stdout()
-    {
-        if (out_stream == nullptr) throw std::system_error(EBADF, std::system_category());
-        return *out_stream;
-    };
+    int wait(void) { return WEXITSTATUS(status); }
+
+private:
     
-    std::istream& stderr() { return *err_stream; };
-   
-    int wait()
+    enum ends_of_pipe { READ = 0, WRITE = 1 };
+
+    void open_pipes(void)
     {
-        int status = 0;
-        waitpid(pid, &status, 0);
-        return WEXITSTATUS(status);
-    };
+        if (pipe(in_pipe) == -1)
+            throw std::system_error(errno, std::system_category());
 
-    void close()
+        if (pipe(out_pipe) == -1)
+        {
+            int pipe_errno = errno;
+            close_pipe(in_pipe);
+            throw std::system_error(pipe_errno, std::system_category());
+        }
+        if (pipe(err_pipe) == -1 )
+        {
+            int pipe_errno = errno;
+            close_pipe(in_pipe);
+            close_pipe(out_pipe);
+            throw std::system_error(pipe_errno, std::system_category());
+        }
+    }
+
+    void close_pipe_end(int pipe[2], enum ends_of_pipe end)
     {
-        in_filebuf->close();
+            if (pipe[end] != -1)
+            {
+                ::close(pipe[end]);
+                pipe[end] = -1;
+            }
     }
-    
-    
-private:
-    
-    enum ends_of_pipe { READ = 0, WRITE = 1 };
 
+    void close_pipe(int pipe[2])
+    {
+        close_pipe_end(pipe, READ);
+        close_pipe_end(pipe, WRITE);
+    }
+
     struct raii_char_str
     {
         raii_char_str(std::string s) : buf(s.c_str(), s.c_str() + s.size() + 1) { };
@@ -99,6 +94,22 @@ class popen
         mutable std::vector<char> buf;
     };
 
+    void slurp_pipe(int fd, std::stringstream *&sink)
+    {
+        char buf[4096];
+
+        while (1)
+        {
+            ssize_t ret = read(out_pipe[READ], buf, sizeof(buf));
+            if (ret == -1)
+                throw std::system_error(errno, std::system_category());
+            else if (ret > 0)
+                sink->write(buf, ret);
+            else
+                break;
+        }
+    }
+
     void run(const std::string& cmd, std::vector<std::string> argv)
     {
         argv.insert(argv.begin(), cmd);
@@ -107,21 +118,17 @@ class popen
       
         if (pid == 0) child(argv);
 
-        ::close(in_pipe[READ]);
-        ::close(out_pipe[WRITE]);
-        ::close(err_pipe[WRITE]);
+        close_pipe_end(in_pipe, READ);
+        close_pipe_end(out_pipe, WRITE);
+        close_pipe_end(err_pipe, WRITE);
         
-        in_filebuf = new __gnu_cxx::stdio_filebuf<char>(in_pipe[WRITE], std::ios_base::out, 1);
-        in_stream  = new std::ostream(in_filebuf);
-        
-        if (out_pipe[READ] != -1)
-        {
-            out_filebuf = new __gnu_cxx::stdio_filebuf<char>(out_pipe[READ], std::ios_base::in, 1);
-            out_stream  = new std::istream(out_filebuf);
-        }
-        
-        err_filebuf = new __gnu_cxx::stdio_filebuf<char>(err_pipe[READ], std::ios_base::in, 1);
-        err_stream  = new std::istream(err_filebuf);
+        slurp_pipe(out_pipe[READ], out_stream);
+        slurp_pipe(err_pipe[READ], err_stream);
+
+        close_pipe_end(out_pipe, READ);
+        close_pipe_end(err_pipe, READ);
+
+        waitpid(pid, &status, 0);
     }
     
     void child(const std::vector<std::string>& argv)
@@ -134,12 +141,9 @@ class popen
             return;
         }
 
-        ::close(in_pipe[READ]);
-        ::close(in_pipe[WRITE]);
-        if (out_pipe[READ] != -1) ::close(out_pipe[READ]);
-        ::close(out_pipe[WRITE]);
-        ::close(err_pipe[READ]);        
-        ::close(err_pipe[WRITE]);
+        close_pipe(in_pipe);
+        close_pipe_end(out_pipe, WRITE);
+        close_pipe_end(err_pipe, WRITE);
         
         std::vector<raii_char_str> real_args(argv.begin(), argv.end());
         std::vector<char*> cargs(real_args.begin(), real_args.end());
@@ -153,18 +157,14 @@ class popen
     }
 
     pid_t pid;
+    int status;
 
     int in_pipe[2];
     int out_pipe[2];
     int err_pipe[2];
    
-    __gnu_cxx::stdio_filebuf<char>* in_filebuf;
-    __gnu_cxx::stdio_filebuf<char>* out_filebuf;
-    __gnu_cxx::stdio_filebuf<char>* err_filebuf;
-
-    std::ostream* in_stream;
-    std::istream* out_stream;
-    std::istream* err_stream;
+    std::stringstream *out_stream;
+    std::stringstream *err_stream;
 };
 
 } // namespace: subprocess
