blob: 95fc277c8854f4eff07d772615e2c4a01069d526 [file] [log] [blame]
Fredrik Lundh43298d12000-07-09 11:35:36 +00001/*
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
12 * it's own redirected standard handles to the 16-bit child.
13
14 * AKA solution to the problem described in KB: Q150956.
15 */
16
Tim Peters7a1f9172002-07-14 22:14:19 +000017#define WIN32_LEAN_AND_MEAN
Fredrik Lundh43298d12000-07-09 11:35:36 +000018#include <windows.h>
Mark Hammonde7fefbf2002-04-03 01:47:00 +000019#include <stdio.h>
Tim Peters7a1f9172002-07-14 22:14:19 +000020#include <stdlib.h> /* for malloc and its friends */
Fredrik Lundh43298d12000-07-09 11:35:36 +000021
22const char *usage =
Neal Norwitzc15acef2002-04-15 22:57:46 +000023"This program is used by Python's os.popen function\n"
Fredrik Lundh43298d12000-07-09 11:35:36 +000024"to work around a limitation in Windows 95/98. It is\n"
Neal Norwitzc15acef2002-04-15 22:57:46 +000025"not designed to be used as a stand-alone program.";
Fredrik Lundh43298d12000-07-09 11:35:36 +000026
27int main(int argc, char *argv[])
28{
29 BOOL bRet;
30 STARTUPINFO si;
31 PROCESS_INFORMATION pi;
Mark Hammondfb439ab2000-08-14 05:04:28 +000032 DWORD exit_code=0;
Mark Hammonde7fefbf2002-04-03 01:47:00 +000033 int cmdlen = 0;
34 int i;
35 char *cmdline, *cmdlinefill;
Fredrik Lundh43298d12000-07-09 11:35:36 +000036
Mark Hammonde7fefbf2002-04-03 01:47:00 +000037 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 Lundh43298d12000-07-09 11:35:36 +000052 return 1;
53 }
Mark Hammonde7fefbf2002-04-03 01:47:00 +000054 /* 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 Lundh43298d12000-07-09 11:35:36 +000083
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 Hammonde7fefbf2002-04-03 01:47:00 +000093 NULL, cmdline,
Fredrik Lundh43298d12000-07-09 11:35:36 +000094 NULL, NULL,
95 TRUE, 0,
96 NULL, NULL,
97 &si, &pi
98 );
99
Mark Hammonde7fefbf2002-04-03 01:47:00 +0000100 free(cmdline);
101
Fredrik Lundh43298d12000-07-09 11:35:36 +0000102 if (bRet) {
Mark Hammondfb439ab2000-08-14 05:04:28 +0000103 if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
104 GetExitCodeProcess(pi.hProcess, &exit_code);
105 }
Fredrik Lundh43298d12000-07-09 11:35:36 +0000106 CloseHandle(pi.hProcess);
107 CloseHandle(pi.hThread);
Mark Hammondfb439ab2000-08-14 05:04:28 +0000108 return exit_code;
Fredrik Lundh43298d12000-07-09 11:35:36 +0000109 }
110
111 return 1;
112}