2015-11-03 21:20:15 +01:00
|
|
|
#include "subprocess.h"
|
|
|
|
#include <cstdio>
|
|
|
|
#include <stdexcept>
|
2018-05-19 16:45:56 +02:00
|
|
|
|
|
|
|
#if !defined(_MSC_VER)
|
2015-11-28 17:06:54 +01:00
|
|
|
#include <sys/wait.h>
|
2018-05-19 16:45:56 +02:00
|
|
|
constexpr const char* openmode = "re";
|
|
|
|
#else
|
|
|
|
#define popen _popen
|
|
|
|
#define pclose _pclose
|
|
|
|
#define WEXITSTATUS(a) a
|
|
|
|
constexpr const char* openmode = "r";
|
|
|
|
#endif
|
2015-11-03 21:20:15 +01:00
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
namespace cpputils {
|
2015-11-03 22:11:09 +01:00
|
|
|
//TODO Exception safety
|
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
namespace {
|
|
|
|
FILE *_call(const string &command) {
|
|
|
|
FILE *subprocess = popen(command.c_str(), openmode);
|
|
|
|
if (!subprocess)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Error starting subprocess "+command);
|
|
|
|
}
|
|
|
|
return subprocess;
|
|
|
|
}
|
2015-11-03 21:20:15 +01:00
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
string _getOutput(FILE *subprocess) {
|
|
|
|
string output;
|
2015-11-03 21:20:15 +01:00
|
|
|
char buffer[1024];
|
2018-05-20 09:14:17 +02:00
|
|
|
while(fgets(buffer, sizeof(buffer), subprocess) != nullptr) {
|
|
|
|
output += buffer;
|
2015-11-03 21:20:15 +01:00
|
|
|
}
|
2018-05-20 09:14:17 +02:00
|
|
|
return output;
|
|
|
|
}
|
2015-11-03 21:20:15 +01:00
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
int _close(FILE *subprocess) {
|
|
|
|
auto returncode = pclose(subprocess);
|
|
|
|
if(returncode == -1) {
|
|
|
|
throw std::runtime_error("Error calling pclose. Errno: " + std::to_string(errno));
|
2015-11-03 21:20:15 +01:00
|
|
|
}
|
2018-05-20 09:14:17 +02:00
|
|
|
if (WIFEXITED(returncode) == 0) {
|
|
|
|
// WEXITSTATUS is only valud if WIFEXITED is 0.
|
|
|
|
throw std::runtime_error("WIFEXITED returned " + std::to_string(WIFEXITED(returncode)));
|
|
|
|
}
|
|
|
|
return WEXITSTATUS(returncode);
|
|
|
|
}
|
2015-11-03 21:20:15 +01:00
|
|
|
}
|
2015-11-03 22:11:09 +01:00
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
SubprocessResult Subprocess::call(const string &command) {
|
2015-11-03 22:11:09 +01:00
|
|
|
FILE *subprocess = _call(command);
|
2018-05-20 09:14:17 +02:00
|
|
|
string output = _getOutput(subprocess);
|
|
|
|
int exitcode = _close(subprocess);
|
2015-11-03 22:11:09 +01:00
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
return SubprocessResult {output, exitcode};
|
2015-11-03 22:11:09 +01:00
|
|
|
}
|
|
|
|
|
2018-05-20 09:14:17 +02:00
|
|
|
SubprocessResult Subprocess::check_call(const string &command) {
|
|
|
|
auto result = call(command);
|
|
|
|
if(result.exitcode != 0) {
|
|
|
|
throw SubprocessError("Subprocess \""+command+"\" exited with code "+std::to_string(result.exitcode));
|
2015-11-03 22:11:09 +01:00
|
|
|
}
|
2018-05-20 09:14:17 +02:00
|
|
|
return result;
|
2015-11-03 22:11:09 +01:00
|
|
|
}
|
2018-05-20 09:14:17 +02:00
|
|
|
|
2015-11-07 09:11:12 +01:00
|
|
|
}
|