mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	- improved os.popen support for windows, based on win32pipe
by Bill Tutt. note: to run this on Windows 95/98, you need to have the w9xpopen.exe helper in the same directory as the python DLL.
This commit is contained in:
		
							parent
							
								
									ce81d59c0c
								
							
						
					
					
						commit
						ffb9c770f8
					
				
					 1 changed files with 462 additions and 6 deletions
				
			
		| 
						 | 
					@ -222,6 +222,7 @@ extern int lstat(const char *, struct stat *);
 | 
				
			||||||
#include <direct.h>
 | 
					#include <direct.h>
 | 
				
			||||||
#include <io.h>
 | 
					#include <io.h>
 | 
				
			||||||
#include <process.h>
 | 
					#include <process.h>
 | 
				
			||||||
 | 
					#define WINDOWS_LEAN_AND_MEAN
 | 
				
			||||||
#include <windows.h>
 | 
					#include <windows.h>
 | 
				
			||||||
#ifdef MS_WIN32
 | 
					#ifdef MS_WIN32
 | 
				
			||||||
#define popen	_popen
 | 
					#define popen	_popen
 | 
				
			||||||
| 
						 | 
					@ -353,6 +354,18 @@ posix_error_with_filename(char* name)
 | 
				
			||||||
	return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
 | 
						return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef MS_WIN32
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					win32_error(char* function, char* filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* XXX this could be improved */
 | 
				
			||||||
 | 
						errno = GetLastError();
 | 
				
			||||||
 | 
						if (filename)
 | 
				
			||||||
 | 
							return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return PyErr_SetFromErrno(PyExc_OSError);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(PYOS_OS2)
 | 
					#if defined(PYOS_OS2)
 | 
				
			||||||
/**********************************************************************
 | 
					/**********************************************************************
 | 
				
			||||||
| 
						 | 
					@ -845,7 +858,7 @@ posix_listdir(PyObject *self, PyObject *args)
 | 
				
			||||||
		errno = GetLastError();
 | 
							errno = GetLastError();
 | 
				
			||||||
		if (errno == ERROR_FILE_NOT_FOUND)
 | 
							if (errno == ERROR_FILE_NOT_FOUND)
 | 
				
			||||||
			return PyList_New(0);
 | 
								return PyList_New(0);
 | 
				
			||||||
		return posix_error_with_filename(name);
 | 
							return win32_error("FindFirstFile", name);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		if (FileData.cFileName[0] == '.' &&
 | 
							if (FileData.cFileName[0] == '.' &&
 | 
				
			||||||
| 
						 | 
					@ -868,10 +881,8 @@ posix_listdir(PyObject *self, PyObject *args)
 | 
				
			||||||
		Py_DECREF(v);
 | 
							Py_DECREF(v);
 | 
				
			||||||
	} while (FindNextFile(hFindFile, &FileData) == TRUE);
 | 
						} while (FindNextFile(hFindFile, &FileData) == TRUE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (FindClose(hFindFile) == FALSE) {
 | 
						if (FindClose(hFindFile) == FALSE)
 | 
				
			||||||
		errno = GetLastError();
 | 
							return win32_error("FindClose", name);
 | 
				
			||||||
		return posix_error_with_filename(name);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return d;
 | 
						return d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2108,6 +2119,446 @@ posix_popen(PyObject *self, PyObject *args)
 | 
				
			||||||
	return f;
 | 
						return f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#elif defined(MS_WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Portable 'popen' replacement for Win32.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Written by Bill Tutt <billtut@microsoft.com>.  Minor tweaks
 | 
				
			||||||
 | 
					 * and 2.0 integration by Fredrik Lundh <fredrik@pythonware.com>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <malloc.h>
 | 
				
			||||||
 | 
					#include <io.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* These tell _PyPopen() wether to return 1, 2, or 3 file objects. */
 | 
				
			||||||
 | 
					#define POPEN_1 1
 | 
				
			||||||
 | 
					#define POPEN_2 2
 | 
				
			||||||
 | 
					#define POPEN_3 3
 | 
				
			||||||
 | 
					#define POPEN_4 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *_PyPopen(char *, int, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* popen that works from a GUI.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The result of this function is a pipe (file) connected to the
 | 
				
			||||||
 | 
					 * processes stdin or stdout, depending on the requested mode.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					posix_popen(PyObject *self, PyObject *args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int bufsize = -1;
 | 
				
			||||||
 | 
						PyObject *f, *s;
 | 
				
			||||||
 | 
						int tm = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						char *cmdstring;
 | 
				
			||||||
 | 
						char *mode = "r";
 | 
				
			||||||
 | 
						if (!PyArg_ParseTuple(args, "s|s:popen", &cmdstring, &mode))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s = PyTuple_New(0);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						if (*mode == 'r')
 | 
				
			||||||
 | 
							tm = _O_RDONLY;
 | 
				
			||||||
 | 
						else if (*mode != 'w') {
 | 
				
			||||||
 | 
							PyErr_SetString(PyExc_ValueError, "mode must be 'r' or 'w'");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							tm = _O_WRONLY;
 | 
				
			||||||
 | 
						 
 | 
				
			||||||
 | 
						if (*(mode+1) == 't')
 | 
				
			||||||
 | 
							f = _PyPopen(cmdstring, tm | _O_TEXT , POPEN_1);
 | 
				
			||||||
 | 
						else if (*(mode+1) == 'b')
 | 
				
			||||||
 | 
							f = _PyPopen(cmdstring, tm | _O_BINARY , POPEN_1);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							f = _PyPopen(cmdstring, tm | _O_TEXT, POPEN_1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Variation on win32pipe.popen
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The result of this function is a pipe (file) connected to the
 | 
				
			||||||
 | 
					 * process's stdin, and a pipe connected to the process's stdout.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					win32_popen2(PyObject *self, PyObject  *args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PyObject *f;
 | 
				
			||||||
 | 
						int tm=0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						char *cmdstring;
 | 
				
			||||||
 | 
						char *mode = "t";
 | 
				
			||||||
 | 
						if (!PyArg_ParseTuple(args, "s|s:popen2", &cmdstring, &mode))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						if (*mode == 't')
 | 
				
			||||||
 | 
							tm = _O_TEXT;
 | 
				
			||||||
 | 
						else if (*mode != 'b') {
 | 
				
			||||||
 | 
							PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							tm = _O_BINARY;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						f = _PyPopen(cmdstring, tm , POPEN_2);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Variation on <om win32pipe.popen>
 | 
				
			||||||
 | 
					 * The result of this function is 3 pipes - the process's stdin,
 | 
				
			||||||
 | 
					 * stdout and stderr
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					win32_popen3(PyObject *self, PyObject *args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PyObject *f;
 | 
				
			||||||
 | 
						int tm = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						char *cmdstring;
 | 
				
			||||||
 | 
						char *mode = "t";
 | 
				
			||||||
 | 
						if (!PyArg_ParseTuple(args, "s|s:Popen3", &cmdstring, &mode))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						if (*mode == 't')
 | 
				
			||||||
 | 
							tm = _O_TEXT;
 | 
				
			||||||
 | 
						else if (*mode != 'b') {
 | 
				
			||||||
 | 
							PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							tm = _O_BINARY;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						f = _PyPopen(cmdstring, tm, POPEN_3);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Variation on win32pipe.popen
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The result of this function is 2 pipes - the processes stdin, 
 | 
				
			||||||
 | 
					 * and stdout+stderr combined as a single pipe.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					win32_popen4(PyObject *self, PyObject  *args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PyObject *f;
 | 
				
			||||||
 | 
						int tm = 0;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						char *cmdstring;
 | 
				
			||||||
 | 
						char *mode = "t";
 | 
				
			||||||
 | 
						if (!PyArg_ParseTuple(args, "s|s:popen4", &cmdstring, &mode))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						if (*mode == 't')
 | 
				
			||||||
 | 
							tm = _O_TEXT;
 | 
				
			||||||
 | 
						else if (*mode != 'b') {
 | 
				
			||||||
 | 
							PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							tm = _O_BINARY;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						f = _PyPopen(cmdstring, tm , POPEN_4);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					_PyPopenCreateProcess(char *cmdstring,
 | 
				
			||||||
 | 
										  HANDLE hStdin,
 | 
				
			||||||
 | 
										  HANDLE hStdout,
 | 
				
			||||||
 | 
										  HANDLE hStderr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PROCESS_INFORMATION piProcInfo;
 | 
				
			||||||
 | 
						STARTUPINFO siStartInfo;
 | 
				
			||||||
 | 
						char *s1,*s2, *s3 = " /c ";
 | 
				
			||||||
 | 
						const char *szConsoleSpawn = "w9xpopen.exe \"";
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (i = GetEnvironmentVariable("COMSPEC",NULL,0)) {
 | 
				
			||||||
 | 
							s1 = (char *)_alloca(i);
 | 
				
			||||||
 | 
							if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
 | 
				
			||||||
 | 
								return x;
 | 
				
			||||||
 | 
							if (GetVersion() < 0x80000000) {
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * NT/2000
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								x = i + strlen(s3) + strlen(cmdstring) + 1;
 | 
				
			||||||
 | 
								s2 = (char *)_alloca(x);
 | 
				
			||||||
 | 
								ZeroMemory(s2, x);
 | 
				
			||||||
 | 
								sprintf(s2, "%s%s%s", s1, s3, cmdstring);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * Oh gag, we're on Win9x. Use the workaround listed in
 | 
				
			||||||
 | 
								 * KB: Q150956
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								char modulepath[256];
 | 
				
			||||||
 | 
								GetModuleFileName(NULL, modulepath, sizeof(modulepath));
 | 
				
			||||||
 | 
								for (i = x = 0; modulepath[i]; i++)
 | 
				
			||||||
 | 
									if (modulepath[i] == '\\')
 | 
				
			||||||
 | 
										x = i+1;
 | 
				
			||||||
 | 
								modulepath[x] = '\0';
 | 
				
			||||||
 | 
								x = i + strlen(s3) + strlen(cmdstring) + 1 +
 | 
				
			||||||
 | 
									strlen(modulepath) + 
 | 
				
			||||||
 | 
									strlen(szConsoleSpawn) + 1;
 | 
				
			||||||
 | 
								s2 = (char *)_alloca(x);
 | 
				
			||||||
 | 
								ZeroMemory(s2, x);
 | 
				
			||||||
 | 
								sprintf(
 | 
				
			||||||
 | 
									s2,
 | 
				
			||||||
 | 
									"%s%s%s%s%s\"",
 | 
				
			||||||
 | 
									modulepath,
 | 
				
			||||||
 | 
									szConsoleSpawn,
 | 
				
			||||||
 | 
									s1,
 | 
				
			||||||
 | 
									s3,
 | 
				
			||||||
 | 
									cmdstring);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Could be an else here to try cmd.exe / command.com in the path
 | 
				
			||||||
 | 
						   Now we'll just error out.. */
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
						ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
 | 
				
			||||||
 | 
						siStartInfo.cb = sizeof(STARTUPINFO);
 | 
				
			||||||
 | 
						siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
 | 
				
			||||||
 | 
						siStartInfo.hStdInput = hStdin;
 | 
				
			||||||
 | 
						siStartInfo.hStdOutput = hStdout;
 | 
				
			||||||
 | 
						siStartInfo.hStdError = hStderr;
 | 
				
			||||||
 | 
						siStartInfo.wShowWindow = SW_HIDE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (CreateProcess(NULL,
 | 
				
			||||||
 | 
										  s2,
 | 
				
			||||||
 | 
										  NULL,
 | 
				
			||||||
 | 
										  NULL,
 | 
				
			||||||
 | 
										  TRUE,
 | 
				
			||||||
 | 
										  CREATE_NEW_CONSOLE,
 | 
				
			||||||
 | 
										  NULL,
 | 
				
			||||||
 | 
										  NULL,
 | 
				
			||||||
 | 
										  &siStartInfo,
 | 
				
			||||||
 | 
										  &piProcInfo) ) {
 | 
				
			||||||
 | 
							/* Close the handles now so anyone waiting is woken. */
 | 
				
			||||||
 | 
							CloseHandle(piProcInfo.hProcess);
 | 
				
			||||||
 | 
							CloseHandle(piProcInfo.hThread);
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following code is based off of KB: Q190351 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					_PyPopen(char *cmdstring, int mode, int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
 | 
				
			||||||
 | 
							hChildStderrRd, hChildStderrWr, hChildStdinWrDup, hChildStdoutRdDup,
 | 
				
			||||||
 | 
							hChildStderrRdDup; /* hChildStdoutWrDup; */
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						SECURITY_ATTRIBUTES saAttr;
 | 
				
			||||||
 | 
						BOOL fSuccess;
 | 
				
			||||||
 | 
						int fd1, fd2, fd3;
 | 
				
			||||||
 | 
						FILE *f1, *f2, *f3;
 | 
				
			||||||
 | 
						PyObject *f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
 | 
				
			||||||
 | 
						saAttr.bInheritHandle = TRUE;
 | 
				
			||||||
 | 
						saAttr.lpSecurityDescriptor = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
 | 
				
			||||||
 | 
							return win32_error("CreatePipe", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create new output read handle and the input write handle. Set
 | 
				
			||||||
 | 
						 * the inheritance properties to FALSE. Otherwise, the child inherits
 | 
				
			||||||
 | 
						 * the these handles; resulting in non-closeable handles to the pipes
 | 
				
			||||||
 | 
						 * being created. */
 | 
				
			||||||
 | 
						 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
 | 
				
			||||||
 | 
													GetCurrentProcess(), &hChildStdinWrDup, 0,
 | 
				
			||||||
 | 
													FALSE,
 | 
				
			||||||
 | 
													DUPLICATE_SAME_ACCESS);
 | 
				
			||||||
 | 
						 if (!fSuccess)
 | 
				
			||||||
 | 
							 return win32_error("DuplicateHandle", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 /* Close the inheritable version of ChildStdin
 | 
				
			||||||
 | 
						that we're using. */
 | 
				
			||||||
 | 
						 CloseHandle(hChildStdinWr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
 | 
				
			||||||
 | 
							 return win32_error("CreatePipe", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
 | 
				
			||||||
 | 
													GetCurrentProcess(), &hChildStdoutRdDup, 0,
 | 
				
			||||||
 | 
													FALSE,
 | 
				
			||||||
 | 
													DUPLICATE_SAME_ACCESS);
 | 
				
			||||||
 | 
						 if (!fSuccess)
 | 
				
			||||||
 | 
							 return win32_error("DuplicateHandle", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 /* Close the inheritable version of ChildStdout
 | 
				
			||||||
 | 
							that we're using. */
 | 
				
			||||||
 | 
						 CloseHandle(hChildStdoutRd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 if (n != POPEN_4) {
 | 
				
			||||||
 | 
							 if (!CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
 | 
				
			||||||
 | 
								 return win32_error("CreatePipe", NULL);
 | 
				
			||||||
 | 
							 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStderrRd,
 | 
				
			||||||
 | 
														GetCurrentProcess(), &hChildStderrRdDup, 0,
 | 
				
			||||||
 | 
														FALSE,
 | 
				
			||||||
 | 
														DUPLICATE_SAME_ACCESS);
 | 
				
			||||||
 | 
							 if (!fSuccess)
 | 
				
			||||||
 | 
								 return win32_error("DuplicateHandle", NULL);
 | 
				
			||||||
 | 
							 /* Close the inheritable version of ChildStdErr that we're using. */
 | 
				
			||||||
 | 
							 CloseHandle(hChildStderrRd);
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						 switch (n) {
 | 
				
			||||||
 | 
						 case POPEN_1:
 | 
				
			||||||
 | 
							 switch (mode & (_O_RDONLY | _O_TEXT | _O_BINARY | _O_WRONLY)) {
 | 
				
			||||||
 | 
							 case _O_WRONLY | _O_TEXT:
 | 
				
			||||||
 | 
								 /* Case for writing to child Stdin in text mode. */
 | 
				
			||||||
 | 
								 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 | 
				
			||||||
 | 
								 f1 = _fdopen(fd1, "w");
 | 
				
			||||||
 | 
								 f = PyFile_FromFile(f1, cmdstring, "w", fclose);
 | 
				
			||||||
 | 
								 PyFile_SetBufSize(f, 0);
 | 
				
			||||||
 | 
								 /* We don't care about these pipes anymore, so close them. */
 | 
				
			||||||
 | 
								 CloseHandle(hChildStdoutRdDup);
 | 
				
			||||||
 | 
								 CloseHandle(hChildStderrRdDup);
 | 
				
			||||||
 | 
								 break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 case _O_RDONLY | _O_TEXT:
 | 
				
			||||||
 | 
								 /* Case for reading from child Stdout in text mode. */
 | 
				
			||||||
 | 
								 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 | 
				
			||||||
 | 
								 f1 = _fdopen(fd1, "r");
 | 
				
			||||||
 | 
								 f = PyFile_FromFile(f1, cmdstring, "r", fclose);
 | 
				
			||||||
 | 
								 PyFile_SetBufSize(f, 0);
 | 
				
			||||||
 | 
								 /* We don't care about these pipes anymore, so close them. */
 | 
				
			||||||
 | 
								 CloseHandle(hChildStdinWrDup);
 | 
				
			||||||
 | 
								 CloseHandle(hChildStderrRdDup);
 | 
				
			||||||
 | 
								 break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 case _O_RDONLY | _O_BINARY:
 | 
				
			||||||
 | 
								 /* Case for readinig from child Stdout in binary mode. */
 | 
				
			||||||
 | 
								 fd1 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 | 
				
			||||||
 | 
								 f1 = _fdopen(fd1, "rb");
 | 
				
			||||||
 | 
								 f = PyFile_FromFile(f1, cmdstring, "rb", fclose);
 | 
				
			||||||
 | 
								 PyFile_SetBufSize(f, 0);
 | 
				
			||||||
 | 
								 /* We don't care about these pipes anymore, so close them. */
 | 
				
			||||||
 | 
								 CloseHandle(hChildStdinWrDup);
 | 
				
			||||||
 | 
								 CloseHandle(hChildStderrRdDup);
 | 
				
			||||||
 | 
								 break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 case _O_WRONLY | _O_BINARY:
 | 
				
			||||||
 | 
								 /* Case for writing to child Stdin in binary mode. */
 | 
				
			||||||
 | 
								 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 | 
				
			||||||
 | 
								 f1 = _fdopen(fd1, "wb");
 | 
				
			||||||
 | 
								 f = PyFile_FromFile(f1, cmdstring, "wb", fclose);
 | 
				
			||||||
 | 
								 PyFile_SetBufSize(f, 0);
 | 
				
			||||||
 | 
								 /* We don't care about these pipes anymore, so close them. */
 | 
				
			||||||
 | 
								 CloseHandle(hChildStdoutRdDup);
 | 
				
			||||||
 | 
								 CloseHandle(hChildStderrRdDup);
 | 
				
			||||||
 | 
								 break;
 | 
				
			||||||
 | 
							 }
 | 
				
			||||||
 | 
							 break;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						 case POPEN_2:
 | 
				
			||||||
 | 
						 case POPEN_4:
 | 
				
			||||||
 | 
						 {
 | 
				
			||||||
 | 
							 char *m1, *m2;
 | 
				
			||||||
 | 
							 PyObject *p1, *p2;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							 if (mode && _O_TEXT) {
 | 
				
			||||||
 | 
								 m1 = "r";
 | 
				
			||||||
 | 
								 m2 = "w";
 | 
				
			||||||
 | 
							 } else {
 | 
				
			||||||
 | 
								 m1 = "rb";
 | 
				
			||||||
 | 
								 m2 = "wb";
 | 
				
			||||||
 | 
							 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 | 
				
			||||||
 | 
							 f1 = _fdopen(fd1, m2);
 | 
				
			||||||
 | 
							 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 | 
				
			||||||
 | 
							 f2 = _fdopen(fd2, m1);
 | 
				
			||||||
 | 
							 p1 = PyFile_FromFile(f1, cmdstring, m2, fclose);
 | 
				
			||||||
 | 
							 PyFile_SetBufSize(p1, 0);
 | 
				
			||||||
 | 
							 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
 | 
				
			||||||
 | 
							 PyFile_SetBufSize(p2, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 if (n != 4)
 | 
				
			||||||
 | 
								 CloseHandle(hChildStderrRdDup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 f = Py_BuildValue("OO",p1,p2);
 | 
				
			||||||
 | 
							 break;
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						 case POPEN_3:
 | 
				
			||||||
 | 
						 {
 | 
				
			||||||
 | 
							 char *m1, *m2;
 | 
				
			||||||
 | 
							 PyObject *p1, *p2, *p3;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							 if (mode && _O_TEXT) {
 | 
				
			||||||
 | 
								 m1 = "r";
 | 
				
			||||||
 | 
								 m2 = "w";
 | 
				
			||||||
 | 
							 } else {
 | 
				
			||||||
 | 
								 m1 = "rb";
 | 
				
			||||||
 | 
								 m2 = "wb";
 | 
				
			||||||
 | 
							 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
 | 
				
			||||||
 | 
							 f1 = _fdopen(fd1, m2);
 | 
				
			||||||
 | 
							 fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
 | 
				
			||||||
 | 
							 f2 = _fdopen(fd2, m1);
 | 
				
			||||||
 | 
							 fd3 = _open_osfhandle((long)hChildStderrRdDup, mode);
 | 
				
			||||||
 | 
							 f3 = _fdopen(fd3, m1);
 | 
				
			||||||
 | 
							 p1 = PyFile_FromFile(f1, cmdstring, m2, fclose);
 | 
				
			||||||
 | 
							 p2 = PyFile_FromFile(f2, cmdstring, m1, fclose);
 | 
				
			||||||
 | 
							 p3 = PyFile_FromFile(f3, cmdstring, m1, fclose);
 | 
				
			||||||
 | 
							 PyFile_SetBufSize(p1, 0);
 | 
				
			||||||
 | 
							 PyFile_SetBufSize(p2, 0);
 | 
				
			||||||
 | 
							 PyFile_SetBufSize(p3, 0);
 | 
				
			||||||
 | 
							 f = Py_BuildValue("OOO",p1,p2,p3);
 | 
				
			||||||
 | 
							 break;
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 if (n == POPEN_4) {
 | 
				
			||||||
 | 
							 if (!_PyPopenCreateProcess(cmdstring,
 | 
				
			||||||
 | 
														hChildStdinRd,
 | 
				
			||||||
 | 
														hChildStdoutWr,
 | 
				
			||||||
 | 
														hChildStdoutWr))
 | 
				
			||||||
 | 
								 return win32_error("CreateProcess", NULL);
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
						 else {
 | 
				
			||||||
 | 
							 if (!_PyPopenCreateProcess(cmdstring,
 | 
				
			||||||
 | 
														hChildStdinRd,
 | 
				
			||||||
 | 
														hChildStdoutWr,
 | 
				
			||||||
 | 
														hChildStderrWr))
 | 
				
			||||||
 | 
								 return win32_error("CreateProcess", NULL);
 | 
				
			||||||
 | 
						 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 /* Child is launched. Close the parents copy of those pipe
 | 
				
			||||||
 | 
						  * handles that only the child should have open.  You need to
 | 
				
			||||||
 | 
						  * make sure that no handles to the write end of the output pipe
 | 
				
			||||||
 | 
						  * are maintained in this process or else the pipe will not close
 | 
				
			||||||
 | 
						  * when the child process exits and the ReadFile will hang. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 if (!CloseHandle(hChildStdinRd))
 | 
				
			||||||
 | 
							 return win32_error("CloseHandle", NULL);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						 if (!CloseHandle(hChildStdoutWr))
 | 
				
			||||||
 | 
							 return win32_error("CloseHandle", NULL);
 | 
				
			||||||
 | 
						  
 | 
				
			||||||
 | 
						 if ((n != 4) && (!CloseHandle(hChildStderrWr)))
 | 
				
			||||||
 | 
							 return win32_error("CloseHandle", NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						 return f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
static PyObject *
 | 
					static PyObject *
 | 
				
			||||||
posix_popen(PyObject *self, PyObject *args)
 | 
					posix_popen(PyObject *self, PyObject *args)
 | 
				
			||||||
| 
						 | 
					@ -2728,7 +3179,7 @@ posix_pipe(PyObject *self, PyObject *args)
 | 
				
			||||||
	ok = CreatePipe(&read, &write, NULL, 0);
 | 
						ok = CreatePipe(&read, &write, NULL, 0);
 | 
				
			||||||
	Py_END_ALLOW_THREADS
 | 
						Py_END_ALLOW_THREADS
 | 
				
			||||||
	if (!ok)
 | 
						if (!ok)
 | 
				
			||||||
		return posix_error();
 | 
							return win32_error("CreatePipe", NULL);
 | 
				
			||||||
	read_fd = _open_osfhandle((intptr_t)read, 0);
 | 
						read_fd = _open_osfhandle((intptr_t)read, 0);
 | 
				
			||||||
	write_fd = _open_osfhandle((intptr_t)write, 1);
 | 
						write_fd = _open_osfhandle((intptr_t)write, 1);
 | 
				
			||||||
	return Py_BuildValue("(ii)", read_fd, write_fd);
 | 
						return Py_BuildValue("(ii)", read_fd, write_fd);
 | 
				
			||||||
| 
						 | 
					@ -4423,6 +4874,11 @@ static PyMethodDef posix_methods[] = {
 | 
				
			||||||
#endif /* HAVE_PLOCK */
 | 
					#endif /* HAVE_PLOCK */
 | 
				
			||||||
#ifdef HAVE_POPEN
 | 
					#ifdef HAVE_POPEN
 | 
				
			||||||
	{"popen",	posix_popen, METH_VARARGS, posix_popen__doc__},
 | 
						{"popen",	posix_popen, METH_VARARGS, posix_popen__doc__},
 | 
				
			||||||
 | 
					#ifdef MS_WIN32
 | 
				
			||||||
 | 
						{"popen2",	win32_popen2, METH_VARARGS},
 | 
				
			||||||
 | 
						{"popen3",	win32_popen3, METH_VARARGS},
 | 
				
			||||||
 | 
						{"popen4",	win32_popen4, METH_VARARGS},
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#endif /* HAVE_POPEN */
 | 
					#endif /* HAVE_POPEN */
 | 
				
			||||||
#ifdef HAVE_SETUID
 | 
					#ifdef HAVE_SETUID
 | 
				
			||||||
	{"setuid",	posix_setuid, METH_VARARGS, posix_setuid__doc__},
 | 
						{"setuid",	posix_setuid, METH_VARARGS, posix_setuid__doc__},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue