[Python-checkins] CVS: python/dist/src/PC w9xpopen.c,1.2,1.3
Mark Hammond
mhammond@users.sourceforge.net
2002年4月02日 17:47:02 -0800
Update of /cvsroot/python/python/dist/src/PC
In directory usw-pr-cvs1:/tmp/cvs-serv27599/PC
Modified Files:
w9xpopen.c
Log Message:
Fix bugs:
457466: popenx() argument mangling hangs python
226766: popen('python -c"...."') tends to hang
Fixes argument quoting in w9xpopen.exe for Windows 9x. w9xpopen.exe
also never attempts to display a MessageBox when not executed
interactively.
Added test_popen() test. This test currently just executes
"python -c ..." as a child process, and checks that the expected
arguments were all recieved correctly by the child process. This
test succeeds for me on Win9x, win2k and Linux, and I hope it does
for other popen supported platforms too :)
Index: w9xpopen.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/PC/w9xpopen.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** w9xpopen.c 14 Aug 2000 05:04:28 -0000 1.2
--- w9xpopen.c 3 Apr 2002 01:47:00 -0000 1.3
***************
*** 17,23 ****
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
const char *usage =
! "This program is used by Python's os.pipe function to\n"
"to work around a limitation in Windows 95/98. It is\n"
"not designed to be used as stand-alone program.";
--- 17,24 ----
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
+ #include <stdio.h>
const char *usage =
! "This program is used by Python's os.popen function to\n"
"to work around a limitation in Windows 95/98. It is\n"
"not designed to be used as stand-alone program.";
***************
*** 29,37 ****
PROCESS_INFORMATION pi;
DWORD exit_code=0;
! if (argc != 2) {
! MessageBox(NULL, usage, argv[0], MB_OK);
return 1;
}
/* Make child process use this app's standard files. */
--- 30,83 ----
PROCESS_INFORMATION pi;
DWORD exit_code=0;
+ int cmdlen = 0;
+ int i;
+ char *cmdline, *cmdlinefill;
! if (argc < 2) {
! if (GetFileType(GetStdHandle(STD_INPUT_HANDLE))==FILE_TYPE_CHAR)
! /* Attached to a console, and therefore not executed by Python
! Display a message box for the inquisitive user
! */
! MessageBox(NULL, usage, argv[0], MB_OK);
! else {
! /* Eeek - executed by Python, but args are screwed!
! Write an error message to stdout so there is at
! least some clue for the end user when it appears
! in their output.
! A message box would be hidden and blocks the app.
! */
! fprintf(stdout, "Internal popen error - no args specified\n%s\n", usage);
! }
return 1;
}
+ /* Build up the command-line from the args.
+ Args with a space are quoted, existing quotes are escaped.
+ To keep things simple calculating the buffer size, we assume
+ every character is a quote - ie, we allocate double what we need
+ in the worst case. As this is only double the command line passed
+ to us, there is a good chance this is reasonably small, so the total
+ allocation will almost always be < 512 bytes.
+ */
+ for (i=1;i<argc;i++)
+ cmdlen += strlen(argv[i])*2 + 3; /* one space, maybe 2 quotes */
+ cmdline = cmdlinefill = (char *)malloc(cmdlen+1);
+ if (cmdline == NULL)
+ return -1;
+ for (i=1;i<argc;i++) {
+ const char *arglook;
+ int bQuote = strchr(argv[i], ' ') != NULL;
+ if (bQuote)
+ *cmdlinefill++ = '"';
+ /* escape quotes */
+ for (arglook=argv[i];*arglook;arglook++) {
+ if (*arglook=='"')
+ *cmdlinefill++ = '\\';
+ *cmdlinefill++ = *arglook;
+ }
+ if (bQuote)
+ *cmdlinefill++ = '"';
+ *cmdlinefill++ = ' ';
+ }
+ *cmdlinefill = '0円';
/* Make child process use this app's standard files. */
***************
*** 44,48 ****
bRet = CreateProcess(
! NULL, argv[1],
NULL, NULL,
TRUE, 0,
--- 90,94 ----
bRet = CreateProcess(
! NULL, cmdline,
NULL, NULL,
TRUE, 0,
***************
*** 50,53 ****
--- 96,101 ----
&si, &pi
);
+
+ free(cmdline);
if (bRet) {