// Copyright (C) 2026 Viorel Munteanu // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. #include "process.h" #include #include #include #include #include ProcessResult run_process(const std::vector& argv) { spdlog::debug("running external command: {}", fmt::join(argv, " ")); int stdout_pipe[2]; if (pipe(stdout_pipe) != 0) { return {-1, ""}; } pid_t pid = fork(); if (pid < 0) { close(stdout_pipe[0]); close(stdout_pipe[1]); return {-1, ""}; } if (pid == 0) { close(stdout_pipe[0]); dup2(stdout_pipe[1], STDOUT_FILENO); close(stdout_pipe[1]); std::vector c_argv; c_argv.reserve(argv.size() + 1); for (const auto& arg : argv) { c_argv.push_back(const_cast(arg.c_str())); } c_argv.push_back(nullptr); execvp(c_argv[0], c_argv.data()); const char* msg = "run_process: execvp failed\n"; write(STDERR_FILENO, msg, std::strlen(msg)); _exit(127); } close(stdout_pipe[1]); std::string output; char buffer[4096]; ssize_t n; while ((n = read(stdout_pipe[0], buffer, sizeof(buffer))) > 0) { output.append(buffer, static_cast(n)); } close(stdout_pipe[0]); int status = 0; waitpid(pid, &status, 0); int exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1; if (exit_code != 0) { spdlog::warn("external command failed (exit code {}): {}", exit_code, fmt::join(argv, " ")); } return {exit_code, output}; }