libcryfs/src/cpp-utils/process/subprocess.cpp

80 lines
2.0 KiB
C++
Raw Normal View History

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