1/*************************************************************************** 2** The BSD 3-Clause License. http://www.opensource.org/licenses/BSD-3-Clause 3** 4** This file is part of 'mingw-builds' project. 5** Copyright (c) 2011,2012,2013 by niXman (i dotty nixman doggy gmail dotty com) 6** All rights reserved. 7** 8** Project: mingw-builds ( http://sourceforge.net/projects/mingwbuilds/ ) 9** 10** Redistribution and use in source and binary forms, with or without 11** modification, are permitted provided that the following conditions are met: 12** - Redistributions of source code must retain the above copyright 13** notice, this list of conditions and the following disclaimer. 14** - Redistributions in binary form must reproduce the above copyright 15** notice, this list of conditions and the following disclaimer in 16** the documentation and/or other materials provided with the distribution. 17** - Neither the name of the 'mingw-builds' nor the names of its contributors may 18** be used to endorse or promote products derived from this software 19** without specific prior written permission. 20** 21** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24** A PARTICULAR PURPOSE ARE DISCLAIMED. 25** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 26** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 31** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32** 33***************************************************************************/ 34 35#include <windows.h> 36 37#include <stdio.h> 38#include <strings.h> 39 40#ifdef _DEBUG 41 #define dbg_printf(...) printf(__VA_ARGS__) 42#else 43 #define dbg_printf(...) do {} while(0) 44#endif 45 46// When built for the Android NDK, values are 47// passed in on the GCC commandline, and when 48// built for mingw-builds, these defaults are 49// used. 50#ifndef GDB_TO_PYTHON_REL_DIR 51 #define GDB_TO_PYTHON_REL_DIR "..\\opt\\bin" 52#endif 53 54#ifndef GDB_EXECUTABLE_ORIG_FILENAME 55 #define GDB_EXECUTABLE_ORIG_FILENAME "gdborig.exe" 56#endif 57 58#ifndef PYTHONHOME_REL_DIR 59 #define PYTHONHOME_REL_DIR "..\\opt" 60#endif 61 62#define DIE_IF_FALSE(var) \ 63 do { \ 64 if ( !(var) ) { \ 65 fprintf(stderr, "%s(%d)[%d]: expression \"%s\" fail. terminate.\n" \ 66 ,__FILE__ \ 67 ,__LINE__ \ 68 ,GetLastError() \ 69 ,#var \ 70 ); \ 71 exit(1); \ 72 } \ 73 } while (0) 74 75int main(int argc, char** argv) { 76 enum { 77 envbufsize = 1024*32 78 ,exebufsize = 1024 79 ,cmdbufsize = envbufsize 80 }; 81 82 char *envbuf, *sep, *resbuf, *cmdbuf; 83 DWORD len, exitCode; 84 STARTUPINFO si; 85 PROCESS_INFORMATION pi; 86 87 DIE_IF_FALSE( 88 (envbuf = (char *)malloc(envbufsize)) 89 ); 90 DIE_IF_FALSE( 91 (cmdbuf = (char *)malloc(cmdbufsize)) 92 ); 93 *cmdbuf = 0; 94 95 DIE_IF_FALSE( 96 GetEnvironmentVariable("PATH", envbuf, envbufsize) 97 ); 98 dbg_printf("env: %s\n", envbuf); 99 100 DIE_IF_FALSE( 101 GetModuleFileName(0, cmdbuf, exebufsize) 102 ); 103 dbg_printf("curdir: %s\n", cmdbuf); 104 105 DIE_IF_FALSE( 106 (sep = strrchr(cmdbuf, '\\')) 107 ); 108 *(sep+1) = 0; 109 strcat(cmdbuf, GDB_TO_PYTHON_REL_DIR); 110 dbg_printf("sep: %s\n", cmdbuf); 111 112 len = strlen(envbuf)+strlen(cmdbuf) 113 +1 /* for envronment separator */ 114 +1; /* for zero-terminator */ 115 116 DIE_IF_FALSE( 117 (resbuf = (char *)malloc(len)) 118 ); 119 120 DIE_IF_FALSE( 121 (snprintf(resbuf, len, "%s;%s", cmdbuf, envbuf) > 0) 122 ); 123 dbg_printf("PATH: %s\n", resbuf); 124 125 DIE_IF_FALSE( 126 SetEnvironmentVariable("PATH", resbuf) 127 ); 128 129 *(sep+1) = 0; 130 strcat(cmdbuf, PYTHONHOME_REL_DIR); 131 dbg_printf("PYTHONHOME: %s\n", cmdbuf); 132 DIE_IF_FALSE( 133 SetEnvironmentVariable("PYTHONHOME", cmdbuf) 134 ); 135 136 *(sep+1) = 0; 137 strcat(cmdbuf, GDB_EXECUTABLE_ORIG_FILENAME" "); 138 139 if ( argc > 1 ) { 140 for ( ++argv; *argv; ++argv ) { 141 len = strlen(cmdbuf); 142 snprintf(cmdbuf+len, cmdbufsize-len, "%s ", *argv); 143 } 144 } 145 dbg_printf("cmd: %s\n", cmdbuf); 146 147 HANDLE ghJob = CreateJobObject(NULL, "Gdb-Wrapper\0"/*NULL*/); 148 if ( ghJob == NULL ) { 149 fprintf(stderr, "Could not create job object\n"); 150 } 151 else{ 152 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 }; 153 // Configure all child processes associated with the job to terminate when the last handle to the job is closed 154 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; 155 if ( SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)) == 0 ) { 156 fprintf(stderr, "Could not SetInformationJobObject\n"); 157 } 158 } 159 160 memset(&si, 0, sizeof(si)); 161 si.cb = sizeof(si); 162 si.dwFlags |= STARTF_USESTDHANDLES; 163 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 164 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 165 si.hStdError = GetStdHandle(STD_ERROR_HANDLE); 166 167 memset(&pi, 0, sizeof(pi)); 168 169 DIE_IF_FALSE( 170 CreateProcess( 171 0 // exe name 172 ,cmdbuf // command line 173 ,0 // process security attributes 174 ,0 // primary thread security attributes 175 ,TRUE // handles are inherited 176 ,0 // creation flags 177 ,0 // use parent's environment 178 ,0 // use parent's current directory 179 ,&si // STARTUPINFO pointer 180 ,&pi // receives PROCESS_INFORMATION 181 ) 182 ); 183 184 if ( ghJob != NULL ) 185 if ( AssignProcessToJobObject(ghJob, pi.hProcess) == 0 ) { 186 fprintf(stderr, "Could not AssignProcessToObject\n"); 187 } 188 189 // Do not handle Ctrl-C in the wrapper 190 SetConsoleCtrlHandler(NULL, TRUE); 191 192 WaitForSingleObject(pi.hProcess, INFINITE); 193 194 DIE_IF_FALSE( 195 GetExitCodeProcess(pi.hProcess, &exitCode) 196 ); 197 198 if ( ghJob != NULL ) 199 CloseHandle(ghJob); 200 CloseHandle( pi.hProcess ); 201 CloseHandle( pi.hThread ); 202 203 free(envbuf); 204 free(resbuf); 205 free(cmdbuf); 206 207 dbg_printf("exiting with exitCode %d", exitCode); 208 209 return exitCode; 210} 211