--- /dev/null
+/*\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