From df03cdf951ca1a0c6a8c0bde7868dbad8a26bf68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Mangano-Tarumi?= Date: Sun, 11 Oct 2020 16:50:50 +0200 Subject: [PATCH] Introduce ot::execute_process --- src/opustags.h | 6 ++++++ src/system.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/opustags.h b/src/opustags.h index 14f280d..5c47702 100644 --- a/src/opustags.h +++ b/src/opustags.h @@ -61,6 +61,7 @@ enum class st { /* System */ badly_encoded, information_lost, + child_process_failed, /* Ogg */ bad_stream, end_of_stream, @@ -162,6 +163,11 @@ private: iconv_t cd; /**< conversion descriptor */ }; +// Execute the process specified in args using execlp. Wait for the process to +// exit and return st::ok on success, or st::child_process_failed if it did not +// exit with 0. +ot::status execute_process(std::string_view arg0, std::string_view arg1); + /** \} */ /***********************************************************************************************//** diff --git a/src/system.cc b/src/system.cc index 2d1dbbf..c4a88e4 100644 --- a/src/system.cc +++ b/src/system.cc @@ -14,8 +14,11 @@ #include #include #include +#include #include +using namespace std::string_literals; + ot::status ot::partial_file::open(const char* destination) { abort(); @@ -132,3 +135,28 @@ ot::status ot::encoding_converter::operator()(const char* in, size_t n, std::str "in string '" + std::string(in, n) + "'."}; return ot::st::ok; } + +ot::status ot::execute_process(std::string_view arg0, std::string_view arg1) +{ + pid_t pid = fork(); + if (pid == -1) { + return {st::standard_error, "Could not fork: "s + strerror(errno)}; + } else if (pid == 0) { + execlp(arg0.data(), arg0.data(), arg1.data(), nullptr); + // execvp only returns on error. Let’s not have a runaway child process and kill it. + fprintf(stderr, "error: execvp failed: %s\n", strerror(errno)); + exit(1); + } + + int status = 0; + if (waitpid(pid, &status, 0) == -1) + return {st::standard_error, "waitpid error: "s + strerror(errno)}; + else if (!WIFEXITED(status)) + return {st::child_process_failed, + "Child process did not terminate normally: "s + strerror(errno)}; + else if (WEXITSTATUS(status) != 0) + return {st::child_process_failed, + "Child process exited with " + std::to_string(WEXITSTATUS(status))}; + + return st::ok; +}