/***************************************************************************
** 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;
}