| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * w9xpopen.c | 
 | 3 |  * | 
 | 4 |  * Serves as an intermediate stub Win32 console application to | 
 | 5 |  * avoid a hanging pipe when redirecting 16-bit console based | 
 | 6 |  * programs (including MS-DOS console based programs and batch | 
 | 7 |  * files) on Window 95 and Windows 98. | 
 | 8 |  * | 
 | 9 |  * This program is to be launched with redirected standard | 
 | 10 |  * handles. It will launch the command line specified 16-bit | 
 | 11 |  * console based application in the same console, forwarding | 
| Georg Brandl | 7eb4b7d | 2005-07-22 21:49:32 +0000 | [diff] [blame] | 12 |  * its own redirected standard handles to the 16-bit child. | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 13 |  | 
 | 14 |  * AKA solution to the problem described in KB: Q150956. | 
 | 15 |  */     | 
 | 16 |  | 
| Tim Peters | 7a1f917 | 2002-07-14 22:14:19 +0000 | [diff] [blame] | 17 | #define WIN32_LEAN_AND_MEAN | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 18 | #include <windows.h> | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 19 | #include <stdio.h> | 
| Tim Peters | 7a1f917 | 2002-07-14 22:14:19 +0000 | [diff] [blame] | 20 | #include <stdlib.h>  /* for malloc and its friends */ | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 21 |  | 
 | 22 | const char *usage = | 
| Neal Norwitz | c15acef | 2002-04-15 22:57:46 +0000 | [diff] [blame] | 23 | "This program is used by Python's os.popen function\n" | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 24 | "to work around a limitation in Windows 95/98.  It is\n" | 
| Neal Norwitz | c15acef | 2002-04-15 22:57:46 +0000 | [diff] [blame] | 25 | "not designed to be used as a stand-alone program."; | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 26 |  | 
 | 27 | int main(int argc, char *argv[]) | 
 | 28 | { | 
 | 29 |     BOOL bRet; | 
 | 30 |     STARTUPINFO si; | 
 | 31 |     PROCESS_INFORMATION pi; | 
| Mark Hammond | fb439ab | 2000-08-14 05:04:28 +0000 | [diff] [blame] | 32 |     DWORD exit_code=0; | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 33 |     int cmdlen = 0; | 
 | 34 |     int i; | 
 | 35 |     char *cmdline, *cmdlinefill; | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 36 |  | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 37 |     if (argc < 2) { | 
 | 38 |         if (GetFileType(GetStdHandle(STD_INPUT_HANDLE))==FILE_TYPE_CHAR) | 
 | 39 |             /* Attached to a console, and therefore not executed by Python | 
 | 40 |                Display a message box for the inquisitive user | 
 | 41 |             */ | 
 | 42 |             MessageBox(NULL, usage, argv[0], MB_OK); | 
 | 43 |         else { | 
 | 44 |             /* Eeek - executed by Python, but args are screwed! | 
 | 45 |                Write an error message to stdout so there is at | 
 | 46 |                least some clue for the end user when it appears | 
 | 47 |                in their output. | 
 | 48 |                A message box would be hidden and blocks the app. | 
 | 49 |              */ | 
 | 50 |             fprintf(stdout, "Internal popen error - no args specified\n%s\n", usage); | 
 | 51 |         } | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 52 |         return 1; | 
 | 53 |     } | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 54 |     /* Build up the command-line from the args. | 
 | 55 |        Args with a space are quoted, existing quotes are escaped. | 
 | 56 |        To keep things simple calculating the buffer size, we assume | 
 | 57 |        every character is a quote - ie, we allocate double what we need | 
 | 58 |        in the worst case.  As this is only double the command line passed | 
 | 59 |        to us, there is a good chance this is reasonably small, so the total  | 
 | 60 |        allocation will almost always be < 512 bytes. | 
 | 61 |     */ | 
 | 62 |     for (i=1;i<argc;i++) | 
 | 63 |         cmdlen += strlen(argv[i])*2 + 3; /* one space, maybe 2 quotes */ | 
 | 64 |     cmdline = cmdlinefill = (char *)malloc(cmdlen+1); | 
 | 65 |     if (cmdline == NULL) | 
 | 66 |         return -1; | 
 | 67 |     for (i=1;i<argc;i++) { | 
 | 68 |         const char *arglook; | 
 | 69 |         int bQuote = strchr(argv[i], ' ') != NULL; | 
 | 70 |         if (bQuote) | 
 | 71 |             *cmdlinefill++ = '"'; | 
 | 72 |         /* escape quotes */ | 
 | 73 |         for (arglook=argv[i];*arglook;arglook++) { | 
 | 74 |             if (*arglook=='"') | 
 | 75 |                 *cmdlinefill++ = '\\'; | 
 | 76 |             *cmdlinefill++ = *arglook; | 
 | 77 |         } | 
 | 78 |         if (bQuote) | 
 | 79 |             *cmdlinefill++ = '"'; | 
 | 80 |         *cmdlinefill++ = ' '; | 
 | 81 |     } | 
 | 82 |     *cmdlinefill = '\0'; | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 83 |  | 
 | 84 |     /* Make child process use this app's standard files. */ | 
 | 85 |     ZeroMemory(&si, sizeof si); | 
 | 86 |     si.cb = sizeof si; | 
 | 87 |     si.dwFlags = STARTF_USESTDHANDLES; | 
 | 88 |     si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); | 
 | 89 |     si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); | 
 | 90 |     si.hStdError = GetStdHandle(STD_ERROR_HANDLE); | 
 | 91 |  | 
 | 92 |     bRet = CreateProcess( | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 93 |         NULL, cmdline, | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 94 |         NULL, NULL, | 
 | 95 |         TRUE, 0, | 
 | 96 |         NULL, NULL, | 
 | 97 |         &si, &pi | 
 | 98 |         ); | 
 | 99 |  | 
| Mark Hammond | e7fefbf | 2002-04-03 01:47:00 +0000 | [diff] [blame] | 100 |     free(cmdline); | 
 | 101 |  | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 102 |     if (bRet) { | 
| Mark Hammond | fb439ab | 2000-08-14 05:04:28 +0000 | [diff] [blame] | 103 |         if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) { | 
 | 104 | 	    GetExitCodeProcess(pi.hProcess, &exit_code); | 
 | 105 | 	} | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 106 |         CloseHandle(pi.hProcess); | 
 | 107 |         CloseHandle(pi.hThread); | 
| Mark Hammond | fb439ab | 2000-08-14 05:04:28 +0000 | [diff] [blame] | 108 |         return exit_code; | 
| Fredrik Lundh | 43298d1 | 2000-07-09 11:35:36 +0000 | [diff] [blame] | 109 |     } | 
 | 110 |  | 
 | 111 |     return 1; | 
 | 112 | } |