summaryrefslogtreecommitdiff
path: root/common/os_win32.cpp
diff options
context:
space:
mode:
authorJosé Fonseca <jose.r.fonseca@gmail.com>2011-11-11 14:56:42 +0000
committerJosé Fonseca <jose.r.fonseca@gmail.com>2011-11-11 20:14:05 +0000
commit03c5d3d41dc219051cbbb8b84ea505e15ff433c4 (patch)
tree9d21052f28cde35524cf8cdf2a57ac66435a4811 /common/os_win32.cpp
parent3984ad2eba8decfcfab3da10964746e0ef8720c7 (diff)
Abstract execv().
Diffstat (limited to 'common/os_win32.cpp')
-rw-r--r--common/os_win32.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/common/os_win32.cpp b/common/os_win32.cpp
index 74d911ca..e156c77b 100644
--- a/common/os_win32.cpp
+++ b/common/os_win32.cpp
@@ -29,6 +29,8 @@
#include <string.h>
#include <stdio.h>
+#include <string>
+
#include "os.hpp"
#include "os_path.hpp"
@@ -97,6 +99,116 @@ Path::exists(void) const
return attrs != INVALID_FILE_ATTRIBUTES;
}
+/**
+ * Determine whether an argument should be quoted.
+ */
+static bool
+needsQuote(const char *arg)
+{
+ char c;
+ while (true) {
+ c = *arg++;
+ if (c == '\0') {
+ break;
+ }
+ if (c == ' ' || c == '\t' || c == '\"') {
+ return true;
+ }
+ if (c == '\\') {
+ c = *arg++;
+ if (c == '\0') {
+ break;
+ }
+ if (c == '"') {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void
+quoteArg(std::string &s, const char *arg)
+{
+ char c;
+ unsigned backslashes = 0;
+
+ s.push_back('"');
+ while (true) {
+ c = *arg++;
+ switch (c)
+ if (c == '\0') {
+ break;
+ } else if (c == '"') {
+ while (backslashes) {
+ s.push_back('\\');
+ --backslashes;
+ }
+ s.push_back('\\');
+ } else {
+ if (c == '\\') {
+ ++backslashes;
+ } else {
+ backslashes = 0;
+ }
+ }
+ s.push_back(c);
+ }
+ s.push_back('"');
+}
+
+int execute(char * const * args)
+{
+ std::string commandLine;
+
+ const char *arg0 = *args;
+ const char *arg;
+ char sep = 0;
+ while ((arg = *args++) != NULL) {
+ if (sep) {
+ commandLine.push_back(sep);
+ }
+
+ if (needsQuote(arg)) {
+ quoteArg(commandLine, arg);
+ } else {
+ commandLine.append(arg);
+ }
+
+ sep = ' ';
+ }
+
+ STARTUPINFO startupInfo;
+ memset(&startupInfo, 0, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+
+ PROCESS_INFORMATION processInformation;
+
+ if (!CreateProcessA(NULL,
+ const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW
+ 0, // process attributes
+ 0, // thread attributes
+ FALSE, // inherit handles
+ 0, // creation flags,
+ NULL, // environment
+ NULL, // current directory
+ &startupInfo,
+ &processInformation
+ )) {
+ log("error: failed to execute %s\n", arg0);
+ }
+
+ WaitForSingleObject(processInformation.hProcess, INFINITE);
+
+ DWORD exitCode = ~0;
+ GetExitCodeProcess(processInformation.hProcess, &exitCode);
+
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ return (int)exitCode;
+}
+
void
log(const char *format, ...)
{