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
main(int argc,char ** argv)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