github.com/openshift/source-to-image@v1.4.1-0.20240516041539-bf52fc02204e/hack/windows/sigintwrap/sigintwrap.c (about) 1 // sigintwrap: wrapper for non-Cygwin executables, capturing Cygwin SIGINTs and 2 // forwarding them as a CTRL+BREAK events to the non-Cygwin executable. After 3 // "Solution For Handling Signals In Non-Cygwin Apps With 4 // SetConsoleCtrlHandler", Anthony DeRosa, 5 // http://marc.info/?l=cygwin&m=111047278517873 6 7 8 #include <sys/cygwin.h> 9 #include <pthread.h> 10 #include <signal.h> 11 #include <stdio.h> 12 #include <unistd.h> 13 #include <windows.h> 14 15 16 static PROCESS_INFORMATION pi; 17 18 19 static void * 20 wait_for_process(void *ptr) { 21 WaitForSingleObject(pi.hProcess, INFINITE); 22 return NULL; 23 } 24 25 26 static void 27 sigint(int signal) { 28 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pi.dwProcessId); 29 } 30 31 32 static int 33 needs_path_conversion(const char *s) { 34 // See winsup/cygwin/environ.cc. 35 return !(strncmp(s, "HOME=", 5) && 36 strncmp(s, "LD_LIBRARY_PATH=", 16) && 37 strncmp(s, "PATH=", 5) && 38 strncmp(s, "TEMP=", 5) && 39 strncmp(s, "TMP=", 4) && 40 strncmp(s, "TMPDIR=", 7)); 41 } 42 43 44 static char * 45 prepare_env() { 46 char **p; 47 48 int len = 1; 49 for(p = environ; *p; p++) 50 if(needs_path_conversion(*p)) { 51 char *eq = strchr(*p, '='); 52 len += eq - *p + 1; 53 len += cygwin_conv_path_list(CCP_POSIX_TO_WIN_A, eq + 1, NULL, 0); 54 } else 55 len += strlen(*p) + 1; 56 57 char *env = (char *)malloc(len); 58 char *e = env; 59 for(p = environ; *p; p++) 60 if(needs_path_conversion(*p)) { 61 char *eq = strchr(*p, '='); 62 e = stpncpy(e, *p, eq - *p + 1); 63 cygwin_conv_path_list(CCP_POSIX_TO_WIN_A, eq + 1, e, env + len - e - 1); 64 while(*e++); 65 } else 66 e = stpcpy(e, *p) + 1; 67 *e = '\0'; 68 69 return env; 70 } 71 72 73 int 74 main(int argc, char **argv) { 75 if(argc != 2) { 76 fprintf(stderr, "usage: %s 'c:\\path\\to\\command.exe [arg...]'\n", 77 argv[0]); 78 return 1; 79 } 80 81 STARTUPINFO si; 82 ZeroMemory(&si, sizeof(si)); 83 si.cb = sizeof(si); 84 85 char *env = prepare_env(); 86 87 if(!CreateProcess(NULL, argv[1], NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP, 88 env, NULL, &si, &pi)) { 89 LPTSTR msg; 90 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 91 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, 92 (LPTSTR)&msg, 0, NULL); 93 fputs(msg, stderr); 94 LocalFree(msg); 95 free(env); 96 return 1; 97 } 98 99 free(env); 100 101 signal(SIGINT, sigint); 102 103 // We call WaitForSingleObject on another thread because it cannot be 104 // interrupted by cygwin signals. pthread_join can be. 105 pthread_t thread; 106 pthread_create(&thread, NULL, wait_for_process, NULL); 107 pthread_join(thread, NULL); 108 109 DWORD exitcode; 110 GetExitCodeProcess(pi.hProcess, &exitcode); 111 112 CloseHandle(pi.hProcess); 113 CloseHandle(pi.hThread); 114 115 return exitcode; 116 }