/*************************************************************************** ** The BSD 3-Clause License. http://www.opensource.org/licenses/BSD-3-Clause ** ** This file is part of 'mingw-builds' project. ** Copyright (c) 2011,2012,2013 by niXman (i dotty nixman doggy gmail dotty com) ** All rights reserved. ** ** Project: mingw-builds ( http://sourceforge.net/projects/mingwbuilds/ ) ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met: ** - Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** - Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the distribution. ** - Neither the name of the 'mingw-builds' nor the names of its contributors may ** be used to endorse or promote products derived from this software ** without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ***************************************************************************/ #include <windows.h> #include <stdio.h> #include <strings.h> #ifdef _DEBUG #define dbg_printf(...) printf(__VA_ARGS__) #else #define dbg_printf(...) do {} while(0) #endif // When built for the Android NDK, values are // passed in on the GCC commandline, and when // built for mingw-builds, these defaults are // used. #ifndef GDB_TO_PYTHON_REL_DIR #define GDB_TO_PYTHON_REL_DIR "..\\opt\\bin" #endif #ifndef GDB_EXECUTABLE_ORIG_FILENAME #define GDB_EXECUTABLE_ORIG_FILENAME "gdborig.exe" #endif #ifndef PYTHONHOME_REL_DIR #define PYTHONHOME_REL_DIR "..\\opt" #endif #define DIE_IF_FALSE(var) \ do { \ if ( !(var) ) { \ fprintf(stderr, "%s(%d)[%d]: expression \"%s\" fail. terminate.\n" \ ,__FILE__ \ ,__LINE__ \ ,GetLastError() \ ,#var \ ); \ exit(1); \ } \ } while (0) int main(int argc, char** argv) { enum { envbufsize = 1024*32 ,exebufsize = 1024 ,cmdbufsize = envbufsize }; char *envbuf, *sep, *resbuf, *cmdbuf; DWORD len, exitCode; STARTUPINFO si; PROCESS_INFORMATION pi; DIE_IF_FALSE( (envbuf = (char *)malloc(envbufsize)) ); DIE_IF_FALSE( (cmdbuf = (char *)malloc(cmdbufsize)) ); *cmdbuf = 0; DIE_IF_FALSE( GetEnvironmentVariable("PATH", envbuf, envbufsize) ); dbg_printf("env: %s\n", envbuf); DIE_IF_FALSE( GetModuleFileName(0, cmdbuf, exebufsize) ); dbg_printf("curdir: %s\n", cmdbuf); DIE_IF_FALSE( (sep = strrchr(cmdbuf, '\\')) ); *(sep+1) = 0; strcat(cmdbuf, GDB_TO_PYTHON_REL_DIR); dbg_printf("sep: %s\n", cmdbuf); len = strlen(envbuf)+strlen(cmdbuf) +1 /* for envronment separator */ +1; /* for zero-terminator */ DIE_IF_FALSE( (resbuf = (char *)malloc(len)) ); DIE_IF_FALSE( (snprintf(resbuf, len, "%s;%s", cmdbuf, envbuf) > 0) ); dbg_printf("PATH: %s\n", resbuf); DIE_IF_FALSE( SetEnvironmentVariable("PATH", resbuf) ); *(sep+1) = 0; strcat(cmdbuf, PYTHONHOME_REL_DIR); dbg_printf("PYTHONHOME: %s\n", cmdbuf); DIE_IF_FALSE( SetEnvironmentVariable("PYTHONHOME", cmdbuf) ); *(sep+1) = 0; strcat(cmdbuf, GDB_EXECUTABLE_ORIG_FILENAME" "); if ( argc > 1 ) { for ( ++argv; *argv; ++argv ) { len = strlen(cmdbuf); snprintf(cmdbuf+len, cmdbufsize-len, "%s ", *argv); } } dbg_printf("cmd: %s\n", cmdbuf); HANDLE ghJob = CreateJobObject(NULL, "Gdb-Wrapper\0"/*NULL*/); if ( ghJob == NULL ) { fprintf(stderr, "Could not create job object\n"); } else{ JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 }; // Configure all child processes associated with the job to terminate when the last handle to the job is closed jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if ( SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)) == 0 ) { fprintf(stderr, "Could not SetInformationJobObject\n"); } } memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); memset(&pi, 0, sizeof(pi)); DIE_IF_FALSE( CreateProcess( 0 // exe name ,cmdbuf // command line ,0 // process security attributes ,0 // primary thread security attributes ,TRUE // handles are inherited ,0 // creation flags ,0 // use parent's environment ,0 // use parent's current directory ,&si // STARTUPINFO pointer ,&pi // receives PROCESS_INFORMATION ) ); if ( ghJob != NULL ) if ( AssignProcessToJobObject(ghJob, pi.hProcess) == 0 ) { fprintf(stderr, "Could not AssignProcessToObject\n"); } // Do not handle Ctrl-C in the wrapper SetConsoleCtrlHandler(NULL, TRUE); WaitForSingleObject(pi.hProcess, INFINITE); DIE_IF_FALSE( GetExitCodeProcess(pi.hProcess, &exitCode) ); if ( ghJob != NULL ) CloseHandle(ghJob); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); free(envbuf); free(resbuf); free(cmdbuf); dbg_printf("exiting with exitCode %d", exitCode); return exitCode; }