Imported Upstream version 0.3.3
[anytun.git] / src / win32 / sysExec.hpp
diff --git a/src/win32/sysExec.hpp b/src/win32/sysExec.hpp
new file mode 100644 (file)
index 0000000..ed5be01
--- /dev/null
@@ -0,0 +1,160 @@
+/*\r
+ *  anytun\r
+ *\r
+ *  The secure anycast tunneling protocol (satp) defines a protocol used\r
+ *  for communication between any combination of unicast and anycast\r
+ *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel\r
+ *  mode and allows tunneling of every ETHER TYPE protocol (e.g.\r
+ *  ethernet, ip, arp ...). satp directly includes cryptography and\r
+ *  message authentication based on the methodes used by SRTP.  It is\r
+ *  intended to deliver a generic, scaleable and secure solution for\r
+ *  tunneling and relaying of packets of any protocol.\r
+ *\r
+ *\r
+ *  Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl, \r
+ *                          Christian Pointner <satp@wirdorange.org>\r
+ *\r
+ *  This file is part of Anytun.\r
+ *\r
+ *  Anytun is free software: you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation, either version 3 of the License, or\r
+ *  any later version.\r
+ *\r
+ *  Anytun is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+#pragma once\r
+#ifndef ANYTUN_sysexec_hpp_INCLUDED\r
+#define ANYTUN_sysexec_hpp_INCLUDED\r
+\r
+#include <algorithm>\r
+#include <iostream> // todo remove\r
+#include <windows.h>\r
+\r
+SysExec::~SysExec()\r
+{\r
+  if(!closed_) {\r
+    CloseHandle(process_info_.hProcess);\r
+    CloseHandle(process_info_.hThread);\r
+  }\r
+}\r
+\r
+STARTUPINFOA getStartupInfo() {\r
+  STARTUPINFOA startup_info;\r
+  startup_info.cb = sizeof(STARTUPINFOA);\r
+  GetStartupInfoA(&startup_info);\r
+\r
+  //startup_info.dwFlags = STARTF_USESTDHANDLES;\r
+  //startup_info.hStdInput = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 0, 0, 0); // INVALID_HANDLE_VALUE;\r
+  //startup_info.hStdOutput = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 0, 0, 0); // INVALID_HANDLE_VALUE;\r
+  //startup_info.hStdError = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 0, 0, 0); // INVALID_HANDLE_VALUE;\r
+  startup_info.dwFlags |= STARTF_USESHOWWINDOW;\r
+  startup_info.wShowWindow = SW_HIDE;\r
+  \r
+  return startup_info;\r
+}\r
+\r
+char const * const BATCH_FILE_EXTS[] = { ".bat", ".cmd" };\r
+int const BATCH_FILE_EXTS_COUNT = sizeof(BATCH_FILE_EXTS) / sizeof(BATCH_FILE_EXTS[0]);\r
+\r
+bool endsWith(std::string const& string, std::string const& suffix) {\r
+  return string.find(suffix, string.size() - suffix.size()) != std::string::npos;\r
+}\r
+\r
+void SysExec::doExec(StringVector args, StringList env)\r
+{\r
+  std::vector<char> arguments;\r
+  \r
+  bool isBatchFile = false;\r
+  for(int i = 0; i < BATCH_FILE_EXTS_COUNT; ++i) {\r
+    if(endsWith(script_, BATCH_FILE_EXTS[i])) {\r
+      isBatchFile = true;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if(isBatchFile) {\r
+    std::string const BATCH_INTERPRETER = "cmd /c \"";\r
+    arguments.insert(arguments.end(), BATCH_INTERPRETER.begin(), BATCH_INTERPRETER.end());\r
+  }\r
+  arguments.push_back('\"');\r
+  arguments.insert(arguments.end(), script_.begin(), script_.end());\r
+  arguments.push_back('\"');\r
+  arguments.push_back(' ');\r
+  \r
+  for(StringVector::const_iterator it = args.begin(); it != args.end(); ++it) {\r
+    arguments.push_back('\"');\r
+    arguments.insert(arguments.end(), it->begin(), it->end());\r
+    arguments.push_back('\"');\r
+    arguments.push_back(' ');\r
+  }\r
+\r
+  if(isBatchFile) {\r
+    arguments.push_back('\"');\r
+  }\r
+  arguments.push_back(0);\r
+  \r
+  STARTUPINFOA startup_info = getStartupInfo();\r
+\r
+  std::map<std::string, std::string> envDict;\r
+  for(StringList::const_iterator it = env.begin(); it != env.begin(); ++it) {\r
+    size_t delimiter_pos = it->find('=');\r
+    envDict.insert(std::make_pair(it->substr(0, delimiter_pos), it->substr(delimiter_pos + 1)));\r
+  }\r
+  std::vector<char> env;\r
+  for(std::map<std::string, std::string>::iterator it = envDict.begin(); it != envDict.end(); ++it) {\r
+    env.insert(env.end(), it->first.begin(), it->first.end());\r
+    env.push_back(0);\r
+  }\r
+  env.push_back(0);\r
+\r
+  if(!CreateProcessA(NULL,\r
+                   &arguments[0],\r
+                   NULL,\r
+                   NULL,\r
+                   false,\r
+                   NULL,\r
+                   &env[0],\r
+                   NULL,\r
+                   &startup_info,\r
+                   &process_info_\r
+                   ))\r
+  {\r
+    cLog.msg(Log::PRIO_ERROR) << "executing script '" << script_ << "' CreateProcess() error: " << GetLastError();\r
+    return;\r
+  }\r
+}\r
+\r
+int SysExec::waitForScript()\r
+{\r
+  DWORD result = WaitForSingleObject(process_info_.hProcess, INFINITE);\r
+  assert(WAIT_OBJECT_0 == result); // WAIT_FAILED, WAIT_TIMEOUT ... ???\r
+  bool success = GetExitCodeProcess(process_info_.hProcess, &return_code_) != 0;\r
+  assert(true == success); // false -> HU?\r
+\r
+  CloseHandle(process_info_.hProcess);\r
+  CloseHandle(process_info_.hThread);\r
+  closed_ = true;\r
+\r
+  return static_cast<int>(return_code_);\r
+}\r
+\r
+void SysExec::waitAndDestroy(SysExec*& s)\r
+{\r
+  if(!s)\r
+    return;\r
+\r
+  s->waitForScript();\r
+  cLog.msg(Log::PRIO_NOTICE) << "script '" << s->script_ << "' returned " << s->return_code_;\r
+\r
+  delete(s);\r
+  s = NULL;\r
+}\r
+\r
+#endif // ANYTUN_sysexec_hpp_INCLUDED\r