1
0
mirror of https://github.com/openshift/source-to-image.git synced 2026-02-05 12:44:54 +01:00
Files
source-to-image/hack/windows/sigintwrap/sigintwrap.c
Jim Minter 251057d7f3 s2i windows build enablement
- enable use of cygwin to build and test s2i
- simplify git and file downloaders
- track posix file permissions on windows
- remove unnecessary runtime.GOOS == "windows" checks
- unit test fixes
2016-11-29 19:17:50 +00:00

117 lines
2.7 KiB
C

// sigintwrap: wrapper for non-Cygwin executables, capturing Cygwin SIGINTs and
// forwarding them as a CTRL+BREAK events to the non-Cygwin executable. After
// "Solution For Handling Signals In Non-Cygwin Apps With
// SetConsoleCtrlHandler", Anthony DeRosa,
// http://marc.info/?l=cygwin&m=111047278517873
#include <sys/cygwin.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <windows.h>
static PROCESS_INFORMATION pi;
static void *
wait_for_process(void *ptr) {
WaitForSingleObject(pi.hProcess, INFINITE);
return NULL;
}
static void
sigint(int signal) {
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pi.dwProcessId);
}
static int
needs_path_conversion(const char *s) {
// See winsup/cygwin/environ.cc.
return !(strncmp(s, "HOME=", 5) &&
strncmp(s, "LD_LIBRARY_PATH=", 16) &&
strncmp(s, "PATH=", 5) &&
strncmp(s, "TEMP=", 5) &&
strncmp(s, "TMP=", 4) &&
strncmp(s, "TMPDIR=", 7));
}
static char *
prepare_env() {
char **p;
int len = 1;
for(p = environ; *p; p++)
if(needs_path_conversion(*p)) {
char *eq = strchr(*p, '=');
len += eq - *p + 1;
len += cygwin_conv_path_list(CCP_POSIX_TO_WIN_A, eq + 1, NULL, 0);
} else
len += strlen(*p) + 1;
char *env = (char *)malloc(len);
char *e = env;
for(p = environ; *p; p++)
if(needs_path_conversion(*p)) {
char *eq = strchr(*p, '=');
e = stpncpy(e, *p, eq - *p + 1);
cygwin_conv_path_list(CCP_POSIX_TO_WIN_A, eq + 1, e, env + len - e - 1);
while(*e++);
} else
e = stpcpy(e, *p) + 1;
*e = '\0';
return env;
}
int
main(int argc, char **argv) {
if(argc != 2) {
fprintf(stderr, "usage: %s 'c:\\path\\to\\command.exe [arg...]'\n",
argv[0]);
return 1;
}
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
char *env = prepare_env();
if(!CreateProcess(NULL, argv[1], NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP,
env, NULL, &si, &pi)) {
LPTSTR msg;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0,
(LPTSTR)&msg, 0, NULL);
fputs(msg, stderr);
LocalFree(msg);
free(env);
return 1;
}
free(env);
signal(SIGINT, sigint);
// We call WaitForSingleObject on another thread because it cannot be
// interrupted by cygwin signals. pthread_join can be.
pthread_t thread;
pthread_create(&thread, NULL, wait_for_process, NULL);
pthread_join(thread, NULL);
DWORD exitcode;
GetExitCodeProcess(pi.hProcess, &exitcode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return exitcode;
}