summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp320
1 files changed, 0 insertions, 320 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp b/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
deleted file mode 100644
index 2010b05db93..00000000000
--- a/Build/source/texk/dvisvgm/dvisvgm-src/src/Process.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/*************************************************************************
-** Process.cpp **
-** **
-** This file is part of dvisvgm -- a fast DVI to SVG converter **
-** Copyright (C) 2005-2021 Martin Gieseking <martin.gieseking@uos.de> **
-** **
-** 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 3 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, see <http://www.gnu.org/licenses/>. **
-*************************************************************************/
-
-#ifdef _WIN32
- #include "windows.hpp"
-#else
- #include <csignal>
- #include <cstring>
- #include <fcntl.h>
- #include <sys/wait.h>
- #include <unistd.h>
-#endif
-
-#include <cstdlib>
-#include "FileSystem.hpp"
-#include "Process.hpp"
-#include "SignalHandler.hpp"
-
-using namespace std;
-
-
-/** Helper class that encapsulates the system-specific parts of
- * running a subprocess and retrieving its terminal output. */
-class Subprocess {
- public:
- enum class State {RUNNING, FINISHED, FAILED};
-
- public:
- Subprocess () =default;
- Subprocess (const Subprocess&) =delete;
- Subprocess (Subprocess&&) =delete;
- ~Subprocess ();
- bool run (const string &cmd, string params);
- bool readFromPipe (string &out);
- State state ();
-
- private:
-#ifdef _WIN32
- HANDLE _pipeReadHandle=NULL; ///< handle of read end of pipe
- HANDLE _childProcHandle=NULL; ///< handle of child process
-#else
- int _readfd=-1; ///< file descriptor of read end of pipe
- pid_t _pid=-1; ///< PID of the subprocess
-#endif
-};
-
-
-Process::Process (string cmd, string paramstr)
- : _cmd(std::move(cmd)), _paramstr(std::move(paramstr))
-{
-}
-
-
-/** Runs the process and waits until it's finished.
- * @param[out] out takes the output written to stdout by the executed subprocess
- * @return true if process terminated properly
- * @throw SignalException if CTRL-C was pressed during execution */
-bool Process::run (string *out) {
- Subprocess subprocess;
- if (!subprocess.run(_cmd, _paramstr))
- return false;
- for (;;) {
- if (out) {
- out->clear();
- subprocess.readFromPipe(*out);
- }
- Subprocess::State state = subprocess.state();
- if (state != Subprocess::State::RUNNING)
- return state == Subprocess::State::FINISHED;
- SignalHandler::instance().check();
- }
-}
-
-
-/** Runs the process in the given working directory and waits until it's finished.
- * @param[in] dir working directory
- * @param[out] out takes the output written to stdout by the executed process
- * @return true if process terminated properly
- * @throw SignalException if CTRL-C was pressed during execution */
-bool Process::run (const string &dir, string *out) {
- bool ret = false;
- string cwd = FileSystem::getcwd();
- if (FileSystem::chdir(dir)) {
- ret = run(out);
- ret &= FileSystem::chdir(cwd);
- }
- return ret;
-}
-
-// system-specific stuff
-
-#ifdef _WIN32
-
-static inline void close_and_zero_handle (HANDLE &handle) {
- CloseHandle(handle);
- handle = NULL;
-}
-
-
-Subprocess::~Subprocess () {
- if (_pipeReadHandle != NULL)
- CloseHandle(_pipeReadHandle);
- if (_childProcHandle != NULL) {
- TerminateProcess(_childProcHandle, 1);
- CloseHandle(_childProcHandle);
- }
-}
-
-
-/** Retrieves output generated by child process.
- * @param[out] out read output is appended to this string
- * @returns false on errors */
-bool Subprocess::readFromPipe (string &out) {
- if (!_pipeReadHandle)
- return false;
-
- bool success=false;
- bool processExited=false;
- DWORD len=0;
- while (PeekNamedPipe(_pipeReadHandle, NULL, 0, NULL, &len, NULL)) { // prevent blocking
- if (len == 0) {
- if (processExited)
- break;
- // process still busy
- processExited = (!_childProcHandle || WaitForSingleObject(_childProcHandle, 100) != WAIT_TIMEOUT);
- }
- else {
- char buf[4096];
- success = ReadFile(_pipeReadHandle, buf, sizeof(buf), &len, NULL);
- if (!success || len == 0)
- break;
- out.append(buf, len);
- }
- }
- return success;
-}
-
-
-/** Starts a child process.
- * @param[in] cmd name of command to execute
- * @param[in] paramstr parameters required by command
- * @returns true if child process started properly */
-bool Subprocess::run (const string &cmd, string paramstr) {
- SECURITY_ATTRIBUTES securityAttribs;
- ZeroMemory(&securityAttribs, sizeof(SECURITY_ATTRIBUTES));
- securityAttribs.nLength = sizeof(SECURITY_ATTRIBUTES);
- securityAttribs.bInheritHandle = true;
-
- HANDLE pipeWriteHandle; // write end of pipe
- if (CreatePipe(&_pipeReadHandle, &pipeWriteHandle, &securityAttribs, 0) == ERROR_INVALID_HANDLE)
- return false;
-
- SetHandleInformation(_pipeReadHandle, HANDLE_FLAG_INHERIT, 0);
- HANDLE nullFile = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &securityAttribs, OPEN_EXISTING, 0, NULL);
- bool success = false;
- if (nullFile != INVALID_HANDLE_VALUE) {
- STARTUPINFO startupInfo;
- ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
- startupInfo.cb = sizeof(STARTUPINFO);
- startupInfo.dwFlags = STARTF_USESTDHANDLES;
- startupInfo.hStdInput = nullFile;
- startupInfo.hStdOutput = pipeWriteHandle;
- startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-
- PROCESS_INFORMATION processInfo;
- ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
-
- string cmdline = cmd + " " + paramstr;
- // put subprocess in separate process group to prevent its termination in case of CTRL-C
- success = CreateProcess(NULL, (LPSTR)cmdline.c_str(), NULL, NULL, true, CREATE_NEW_PROCESS_GROUP, NULL, NULL, &startupInfo, &processInfo);
- if (success) {
- _childProcHandle = processInfo.hProcess;
- CloseHandle(processInfo.hThread);
- }
- CloseHandle(nullFile);
- }
- CloseHandle(pipeWriteHandle); // must be closed before reading from pipe to prevent blocking
- if (!success)
- close_and_zero_handle(_pipeReadHandle);
- return success;
-}
-
-
-/** Returns the current state of the child process. */
-Subprocess::State Subprocess::state () {
- DWORD status;
- if (!GetExitCodeProcess(_childProcHandle, &status))
- return State::FAILED;
- if (status == STILL_ACTIVE)
- return State::RUNNING;
- close_and_zero_handle(_childProcHandle);
- return status == 0 ? State::FINISHED : State::FAILED;
-}
-
-#else // !_WIN32
-
-Subprocess::~Subprocess () {
- if (_readfd >= 0)
- close(_readfd);
- if (_pid > 0)
- kill(_pid, SIGKILL);
-}
-
-
-/** Retrieves output generated by child process.
- * @param[out] out read output is appended to this string
- * @returns false on errors */
-bool Subprocess::readFromPipe (string &out) {
- if (_readfd < 0 || _pid < 0)
- return false;
-
- char buf[1024];
- ssize_t len;
- while ((len = read(_readfd, buf, sizeof(buf))) > 0)
- out.append(buf, len);
- if (len < 0) {
- close(_readfd);
- _readfd = -1;
- }
- return len >= 0;
-}
-
-
-/** Extracts whitespace-separated parameters from a string.
- * @param[in,out] paramstr the parameter string
- * @param[out] params vector holding pointers to the extracted parameters */
-static void split_paramstr (string &paramstr, vector<const char*> &params) {
- size_t left=0, right=0; // index of first and last character of current parameter
- char quote=0; // current quote character, 0=none
- const size_t len = paramstr.length();
- while (left <= right && right < len) {
- while (left < len && isspace(paramstr[left]))
- ++left;
- if (left < len && (paramstr[left] == '"' || paramstr[left] == '\''))
- quote = paramstr[left++];
- right = left;
- while (right < len && (quote || !isspace(paramstr[right]))) {
- if (quote && paramstr[right] == quote) {
- quote=0;
- break;
- }
- else
- ++right;
- }
- if (right < len)
- paramstr[right]=0;
- if (left < len)
- params.push_back(&paramstr[left]);
- left = ++right;
- }
-}
-
-
-/** Starts a child process.
- * @param[in] cmd name of command to execute or absolute path to executable
- * @param[in] paramstr parameters required by the command
- * @returns true if child process started properly */
-bool Subprocess::run (const string &cmd, string paramstr) {
- int pipefd[2];
- if (cmd.empty() || pipe(pipefd) < 0)
- return false;
-
- _pid = fork();
- if (_pid < 0) {
- close(pipefd[0]);
- close(pipefd[1]);
- return false;
- }
- if (_pid == 0) { // child process
- dup2(pipefd[1], STDOUT_FILENO); // redirect stdout to the pipe
- dup2(pipefd[1], STDERR_FILENO); // redirect stderr to the pipe
- close(pipefd[0]);
- close(pipefd[1]);
-
- vector<const char*> params;
- params.push_back(cmd.c_str());
- split_paramstr(paramstr, params);
- params.push_back(nullptr); // trailing null pointer marks end of parameter list
- signal(SIGINT, SIG_IGN); // child process is supposed to ignore ctrl-c events
- if (params[0][0] == '/') // absolute path to executable?
- params[0] = strrchr(params[0], '/')+1; // filename of executable
- execvp(cmd.c_str(), const_cast<char* const*>(params.data()));
- exit(1);
- }
- _readfd = pipefd[0];
- close(pipefd[1]); // close write end of pipe
- return true;
-}
-
-
-/** Returns the current state of the child process. */
-Subprocess::State Subprocess::state () {
- int status;
- pid_t wpid = waitpid(_pid, &status, WNOHANG);
- if (wpid == 0)
- return State::RUNNING; // still running
- _pid = -1;
- if (wpid > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
- return State::FINISHED;
- return State::FAILED;
-}
-
-#endif // !_WIN32