blob: 8c063ac0c66c7f31d491ce200b28c1f46eac2c5b [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
17#define WINDOWS_LEAN_AND_MEAN
18#include <windows.h>
Mark Hammonde7fefbf2002-04-03 01:47:00 +000019#include <stdio.h>
Fredrik Lundh43298d12000-07-09 11:35:36 +000020
21const char *usage =
Neal Norwitzc15acef2002-04-15 22:57:46 +000022"This program is used by Python's os.popen function\n"
Fredrik Lundh43298d12000-07-09 11:35:36 +000023"to work around a limitation in Windows 95/98. It is\n"
Neal Norwitzc15acef2002-04-15 22:57:46 +000024"not designed to be used as a stand-alone program.";
Fredrik Lundh43298d12000-07-09 11:35:36 +000025
26int main(int argc, char *argv[])
27{
28 BOOL bRet;
29 STARTUPINFO si;
30 PROCESS_INFORMATION pi;
Mark Hammondfb439ab2000-08-14 05:04:28 +000031 DWORD exit_code=0;
Mark Hammonde7fefbf2002-04-03 01:47:00 +000032 int cmdlen = 0;
33 int i;
34 char *cmdline, *cmdlinefill;
Fredrik Lundh43298d12000-07-09 11:35:36 +000035
Mark Hammonde7fefbf2002-04-03 01:47:00 +000036 if (argc < 2) {
37 if (GetFileType(GetStdHandle(STD_INPUT_HANDLE))==FILE_TYPE_CHAR)
38 /* Attached to a console, and therefore not executed by Python
39 Display a message box for the inquisitive user
40 */
41 MessageBox(NULL, usage, argv[0], MB_OK);
42 else {
43 /* Eeek - executed by Python, but args are screwed!
44 Write an error message to stdout so there is at
45 least some clue for the end user when it appears
46 in their output.
47 A message box would be hidden and blocks the app.
48 */
49 fprintf(stdout, "Internal popen error - no args specified\n%s\n", usage);
50 }
Fredrik Lundh43298d12000-07-09 11:35:36 +000051 return 1;
52 }
Mark Hammonde7fefbf2002-04-03 01:47:00 +000053 /* Build up the command-line from the args.
54 Args with a space are quoted, existing quotes are escaped.
55 To keep things simple calculating the buffer size, we assume
56 every character is a quote - ie, we allocate double what we need
57 in the worst case. As this is only double the command line passed
58 to us, there is a good chance this is reasonably small, so the total
59 allocation will almost always be < 512 bytes.
60 */
61 for (i=1;i<argc;i++)
62 cmdlen += strlen(argv[i])*2 + 3; /* one space, maybe 2 quotes */
63 cmdline = cmdlinefill = (char *)malloc(cmdlen+1);
64 if (cmdline == NULL)
65 return -1;
66 for (i=1;i<argc;i++) {
67 const char *arglook;
68 int bQuote = strchr(argv[i], ' ') != NULL;
69 if (bQuote)
70 *cmdlinefill++ = '"';
71 /* escape quotes */
72 for (arglook=argv[i];*arglook;arglook++) {
73 if (*arglook=='"')
74 *cmdlinefill++ = '\\';
75 *cmdlinefill++ = *arglook;
76 }
77 if (bQuote)
78 *cmdlinefill++ = '"';
79 *cmdlinefill++ = ' ';
80 }
81 *cmdlinefill = '\0';
Fredrik Lundh43298d12000-07-09 11:35:36 +000082
83 /* Make child process use this app's standard files. */
84 ZeroMemory(&si, sizeof si);
85 si.cb = sizeof si;
86 si.dwFlags = STARTF_USESTDHANDLES;
87 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
88 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
89 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
90
91 bRet = CreateProcess(
Mark Hammonde7fefbf2002-04-03 01:47:00 +000092 NULL, cmdline,
Fredrik Lundh43298d12000-07-09 11:35:36 +000093 NULL, NULL,
94 TRUE, 0,
95 NULL, NULL,
96 &si, &pi
97 );
98
Mark Hammonde7fefbf2002-04-03 01:47:00 +000099 free(cmdline);
100
Fredrik Lundh43298d12000-07-09 11:35:36 +0000101 if (bRet) {
Mark Hammondfb439ab2000-08-14 05:04:28 +0000102 if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) {
103 GetExitCodeProcess(pi.hProcess, &exit_code);
104 }
Fredrik Lundh43298d12000-07-09 11:35:36 +0000105 CloseHandle(pi.hProcess);
106 CloseHandle(pi.hThread);
Mark Hammondfb439ab2000-08-14 05:04:28 +0000107 return exit_code;
Fredrik Lundh43298d12000-07-09 11:35:36 +0000108 }
109
110 return 1;
111}