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 75 int 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