ยปCore Development>Code coverage>PC/w9xpopen.c

Python code coverage for PC/w9xpopen.c

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