summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp b/Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp
new file mode 100644
index 00000000000..af9112b3fe4
--- /dev/null
+++ b/Build/source/texk/dvisvgm/dvisvgm-1.0.12/src/Process.cpp
@@ -0,0 +1,143 @@
+/*************************************************************************
+** Process.cpp **
+** **
+** This file is part of dvisvgm -- the DVI to SVG converter **
+** Copyright (C) 2005-2012 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.h>
+#else
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#endif
+
+#include <cstdlib>
+#include "FileSystem.h"
+#include "Process.h"
+#include "SignalHandler.h"
+#include "macros.h"
+
+using namespace std;
+
+Process::Process (const string &cmd, const string &paramstr)
+ : _cmd(cmd), _paramstr(paramstr)
+{
+}
+
+
+#ifndef __WIN32__
+/** Extracts whitespace-sparated parameters from a string.
+ * @param[in] paramstr the parameter string
+ * @param[out] params vector holding 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;
+ }
+}
+#endif
+
+
+/** Runs the process and waits until it's finished.
+ * @param[in] quiet if true, output to stdout/stderr is suppressed
+ * @return true if process terminated properly
+ * @throw SignalException if CTRL-C was pressed during execution */
+bool Process::run (bool quiet) {
+#ifdef __WIN32__
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = true;
+
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ HANDLE devnull = CreateFile("nul", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.hStdOutput = quiet ? devnull : GetStdHandle(STD_OUTPUT_HANDLE);
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&pi, sizeof(pi));
+
+ string cmdline = _cmd+" "+_paramstr;
+ CreateProcess(NULL, (LPSTR)cmdline.c_str(), NULL, NULL, true, 0, NULL, NULL, &si, &pi);
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ DWORD exitcode = (DWORD)-1;
+ GetExitCodeProcess(pi.hProcess, &exitcode);
+ CloseHandle(devnull);
+ return exitcode == 0;
+#else
+ pid_t pid = fork();
+ if (pid == 0) { // child process
+ if (quiet) {
+ int devnull = open(FileSystem::DEVNULL, O_WRONLY);
+ if (devnull >= 0) {
+ dup2(devnull, STDOUT_FILENO);
+ dup2(devnull, STDERR_FILENO);
+ close(devnull);
+ }
+ }
+ vector<const char*> params;
+ params.push_back(_cmd.c_str());
+ split_paramstr(_paramstr, params);
+ params.push_back(0); // trailing NULL marks end
+ execvp(_cmd.c_str(), const_cast<char* const*>(&params[0]));
+ exit(1);
+ }
+ if (pid > 0) { // main process
+ int status;
+ for (;;) {
+ waitpid(pid, &status, WNOHANG);
+ if (WIFEXITED(status)) // child process exited normally
+ return WEXITSTATUS(status) == 0;
+
+ try {
+ SignalHandler::instance().check();
+ }
+ catch (SignalException &e) { // caught ctrl-c
+ kill(pid, SIGKILL);
+ throw e;
+ }
+ }
+ }
+ return false;
+#endif
+}
+