1
/*************************************************************************
4
** This file is part of dvisvgm -- the DVI to SVG converter **
5
** Copyright (C) 2005-2014 Martin Gieseking <martin.gieseking@uos.de> **
7
** This program is free software; you can redistribute it and/or **
8
** modify it under the terms of the GNU General Public License as **
9
** published by the Free Software Foundation; either version 3 of **
10
** the License, or (at your option) any later version. **
12
** This program is distributed in the hope that it will be useful, but **
13
** WITHOUT ANY WARRANTY; without even the implied warranty of **
14
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **
15
** GNU General Public License for more details. **
17
** You should have received a copy of the GNU General Public License **
18
** along with this program; if not, see <http://www.gnu.org/licenses/>. **
19
*************************************************************************/
33
#include "FileSystem.h"
35
#include "SignalHandler.h"
40
Process::Process (const string &cmd, const string ¶mstr)
41
: _cmd(cmd), _paramstr(paramstr)
47
static void pipe_read (HANDLE handle, string &out) {
52
bool success = ReadFile(handle, buf, 1024, &num_chars, NULL);
53
if (!success || num_chars == 0)
55
out.append(buf, num_chars);
57
// remove trailing space
59
int pos = out.size()-1;
60
while (pos >= 0 && isspace(out[pos]))
67
static inline void close_handle (HANDLE handle) {
74
/** Extracts whitespace-sparated parameters from a string.
75
* @param[in] paramstr the parameter string
76
* @param[out] params vector holding the extracted parameters */
77
static void split_paramstr (string paramstr, vector<const char*> ¶ms) {
78
size_t left=0, right=0; // index of first and last character of current parameter
79
char quote=0; // current quote character, 0=none
80
const size_t len = paramstr.length();
81
while (left <= right && right < len) {
82
while (left < len && isspace(paramstr[left]))
84
if (left < len && (paramstr[left] == '"' || paramstr[left] == '\''))
85
quote = paramstr[left++];
87
while (right < len && (quote || !isspace(paramstr[right]))) {
88
if (quote && paramstr[right] == quote) {
98
params.push_back(¶mstr[left]);
106
/** Runs the process and waits until it's finished.
107
* @param[out] out takes the output written to stdout by the executed process
108
* @return true if process terminated properly
109
* @throw SignalException if CTRL-C was pressed during execution */
110
bool Process::run (string *out) {
112
SECURITY_ATTRIBUTES sa;
113
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
114
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
115
sa.bInheritHandle = true;
118
ZeroMemory(&si, sizeof(STARTUPINFO));
119
si.cb = sizeof(STARTUPINFO);
120
si.dwFlags = STARTF_USESTDHANDLES;
121
HANDLE devnull = NULL;
122
HANDLE proc_read_handle = NULL;
123
HANDLE proc_write_handle = NULL;
125
CreatePipe(&proc_read_handle, &proc_write_handle, &sa, 0);
126
SetHandleInformation(proc_read_handle, HANDLE_FLAG_INHERIT, 0);
127
si.hStdOutput = proc_write_handle;
130
devnull = CreateFile("nul", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
131
si.hStdOutput = devnull;
133
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
134
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
136
PROCESS_INFORMATION pi;
137
ZeroMemory(&pi, sizeof(pi));
138
DWORD exitcode = DWORD(-1);
139
string cmdline = _cmd+" "+_paramstr;
140
bool success = CreateProcess(NULL, (LPSTR)cmdline.c_str(), NULL, NULL, true, 0, NULL, NULL, &si, &pi);
142
WaitForSingleObject(pi.hProcess, INFINITE);
143
GetExitCodeProcess(pi.hProcess, &exitcode);
144
CloseHandle(pi.hProcess);
145
CloseHandle(pi.hThread);
147
close_handle(proc_write_handle); // must be closed before reading from pipe to prevent blocking
149
pipe_read(proc_read_handle, *out);
150
close_handle(proc_read_handle);
151
close_handle(devnull);
152
return exitcode == 0;
155
if (pid == 0) { // child process
157
int devnull = open(FileSystem::DEVNULL, O_WRONLY);
159
dup2(devnull, STDOUT_FILENO);
160
dup2(devnull, STDERR_FILENO);
164
vector<const char*> params;
165
params.push_back(_cmd.c_str());
166
split_paramstr(_paramstr, params);
167
params.push_back(0); // trailing NULL marks end
168
execvp(_cmd.c_str(), const_cast<char* const*>(¶ms[0]));
171
if (pid > 0) { // main process
174
waitpid(pid, &status, WNOHANG);
175
if (WIFEXITED(status)) // child process exited normally
176
return WEXITSTATUS(status) == 0;
179
SignalHandler::instance().check();
181
catch (SignalException &e) { // caught ctrl-c