224 lines
6.4 KiB
Plaintext
224 lines
6.4 KiB
Plaintext
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
|