2 * support routines for subprocess module
4 * Currently, this extension module is only required when using the
5 * subprocess module on Windows, but in the future, stubs for other
6 * platforms might be added here as well.
8 * Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
9 * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
10 * Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
12 * By obtaining, using, and/or copying this software and/or its
13 * associated documentation, you agree that you have read, understood,
14 * and will comply with the following terms and conditions:
16 * Permission to use, copy, modify, and distribute this software and
17 * its associated documentation for any purpose and without fee is
18 * hereby granted, provided that the above copyright notice appears in
19 * all copies, and that both that copyright notice and this permission
20 * notice appear in supporting documentation, and that the name of the
21 * authors not be used in advertising or publicity pertaining to
22 * distribution of the software without specific, written prior
25 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
29 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
30 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
31 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 /* Licensed to PSF under a Contributor Agreement. */
36 /* See http://www.python.org/2.4/license for licensing details. */
38 /* TODO: handle unicode command lines? */
39 /* TODO: handle unicode environment? */
43 #define WINDOWS_LEAN_AND_MEAN
46 /* -------------------------------------------------------------------- */
47 /* handle wrapper. note that this library uses integers when passing
48 handles to a function, and handle wrappers when returning handles.
49 the wrapper is used to provide Detach and Close methods */
56 staticforward PyTypeObject sp_handle_type
;
59 sp_handle_new(HANDLE handle
)
61 sp_handle_object
* self
;
63 self
= PyObject_NEW(sp_handle_object
, &sp_handle_type
);
67 self
->handle
= handle
;
69 return (PyObject
*) self
;
73 sp_handle_detach(sp_handle_object
* self
, PyObject
* args
)
77 if (! PyArg_ParseTuple(args
, ":Detach"))
80 handle
= self
->handle
;
84 /* note: return the current handle, as an integer */
85 return PyInt_FromLong((long) handle
);
89 sp_handle_close(sp_handle_object
* self
, PyObject
* args
)
91 if (! PyArg_ParseTuple(args
, ":Close"))
94 if (self
->handle
!= INVALID_HANDLE_VALUE
) {
95 CloseHandle(self
->handle
);
96 self
->handle
= INVALID_HANDLE_VALUE
;
103 sp_handle_dealloc(sp_handle_object
* self
)
105 if (self
->handle
!= INVALID_HANDLE_VALUE
)
106 CloseHandle(self
->handle
);
110 static PyMethodDef sp_handle_methods
[] = {
111 {"Detach", (PyCFunction
) sp_handle_detach
, 1},
112 {"Close", (PyCFunction
) sp_handle_close
, 1},
117 sp_handle_getattr(sp_handle_object
* self
, char* name
)
119 return Py_FindMethod(sp_handle_methods
, (PyObject
*) self
, name
);
123 sp_handle_as_int(sp_handle_object
* self
)
125 return PyInt_FromLong((long) self
->handle
);
128 static PyNumberMethods sp_handle_as_number
;
130 statichere PyTypeObject sp_handle_type
= {
131 PyObject_HEAD_INIT(NULL
)
133 "_subprocess_handle", sizeof(sp_handle_object
), 0,
134 (destructor
) sp_handle_dealloc
, /*tp_dealloc*/
136 (getattrfunc
) sp_handle_getattr
,/*tp_getattr*/
140 &sp_handle_as_number
, /*tp_as_number */
141 0, /*tp_as_sequence */
142 0, /*tp_as_mapping */
146 /* -------------------------------------------------------------------- */
147 /* windows API functions */
150 sp_GetStdHandle(PyObject
* self
, PyObject
* args
)
155 if (! PyArg_ParseTuple(args
, "i:GetStdHandle", &std_handle
))
158 Py_BEGIN_ALLOW_THREADS
159 handle
= GetStdHandle((DWORD
) std_handle
);
162 if (handle
== INVALID_HANDLE_VALUE
)
163 return PyErr_SetFromWindowsErr(GetLastError());
170 /* note: returns integer, not handle object */
171 return PyInt_FromLong((long) handle
);
175 sp_GetCurrentProcess(PyObject
* self
, PyObject
* args
)
177 if (! PyArg_ParseTuple(args
, ":GetCurrentProcess"))
180 return sp_handle_new(GetCurrentProcess());
184 sp_DuplicateHandle(PyObject
* self
, PyObject
* args
)
186 HANDLE target_handle
;
189 long source_process_handle
;
191 long target_process_handle
;
196 if (! PyArg_ParseTuple(args
, "lllii|i:DuplicateHandle",
197 &source_process_handle
,
199 &target_process_handle
,
205 Py_BEGIN_ALLOW_THREADS
206 result
= DuplicateHandle(
207 (HANDLE
) source_process_handle
,
208 (HANDLE
) source_handle
,
209 (HANDLE
) target_process_handle
,
218 return PyErr_SetFromWindowsErr(GetLastError());
220 return sp_handle_new(target_handle
);
224 sp_CreatePipe(PyObject
* self
, PyObject
* args
)
230 PyObject
* pipe_attributes
; /* ignored */
233 if (! PyArg_ParseTuple(args
, "Oi:CreatePipe", &pipe_attributes
, &size
))
236 Py_BEGIN_ALLOW_THREADS
237 result
= CreatePipe(&read_pipe
, &write_pipe
, NULL
, size
);
241 return PyErr_SetFromWindowsErr(GetLastError());
243 return Py_BuildValue(
244 "NN", sp_handle_new(read_pipe
), sp_handle_new(write_pipe
));
247 /* helpers for createprocess */
250 getint(PyObject
* obj
, char* name
)
254 value
= PyObject_GetAttrString(obj
, name
);
256 PyErr_Clear(); /* FIXME: propagate error? */
259 return (int) PyInt_AsLong(value
);
263 gethandle(PyObject
* obj
, char* name
)
265 sp_handle_object
* value
;
267 value
= (sp_handle_object
*) PyObject_GetAttrString(obj
, name
);
269 PyErr_Clear(); /* FIXME: propagate error? */
272 if (value
->ob_type
!= &sp_handle_type
)
274 return value
->handle
;
278 getenvironment(PyObject
* environment
)
281 PyObject
* out
= NULL
;
286 /* convert environment dictionary to windows enviroment string */
287 if (! PyMapping_Check(environment
)) {
289 PyExc_TypeError
, "environment must be dictionary or None");
293 envsize
= PyMapping_Length(environment
);
295 keys
= PyMapping_Keys(environment
);
296 values
= PyMapping_Values(environment
);
297 if (!keys
|| !values
)
300 out
= PyString_FromStringAndSize(NULL
, 2048);
304 p
= PyString_AS_STRING(out
);
306 for (i
= 0; i
< envsize
; i
++) {
307 int ksize
, vsize
, totalsize
;
308 PyObject
* key
= PyList_GET_ITEM(keys
, i
);
309 PyObject
* value
= PyList_GET_ITEM(values
, i
);
311 if (! PyString_Check(key
) || ! PyString_Check(value
)) {
312 PyErr_SetString(PyExc_TypeError
,
313 "environment can only contain strings");
316 ksize
= PyString_GET_SIZE(key
);
317 vsize
= PyString_GET_SIZE(value
);
318 totalsize
= (p
- PyString_AS_STRING(out
)) + ksize
+ 1 +
320 if (totalsize
> PyString_GET_SIZE(out
)) {
321 int offset
= p
- PyString_AS_STRING(out
);
322 _PyString_Resize(&out
, totalsize
+ 1024);
323 p
= PyString_AS_STRING(out
) + offset
;
325 memcpy(p
, PyString_AS_STRING(key
), ksize
);
328 memcpy(p
, PyString_AS_STRING(value
), vsize
);
333 /* add trailing null byte */
335 _PyString_Resize(&out
, p
- PyString_AS_STRING(out
));
337 /* PyObject_Print(out, stdout, 0); */
352 sp_CreateProcess(PyObject
* self
, PyObject
* args
)
355 PROCESS_INFORMATION pi
;
357 PyObject
* environment
;
359 char* application_name
;
361 PyObject
* process_attributes
; /* ignored */
362 PyObject
* thread_attributes
; /* ignored */
365 PyObject
* env_mapping
;
366 char* current_directory
;
367 PyObject
* startup_info
;
369 if (! PyArg_ParseTuple(args
, "zzOOiiOzO:CreateProcess",
381 ZeroMemory(&si
, sizeof(si
));
384 /* note: we only support a small subset of all SI attributes */
385 si
.dwFlags
= getint(startup_info
, "dwFlags");
386 si
.wShowWindow
= getint(startup_info
, "wShowWindow");
387 si
.hStdInput
= gethandle(startup_info
, "hStdInput");
388 si
.hStdOutput
= gethandle(startup_info
, "hStdOutput");
389 si
.hStdError
= gethandle(startup_info
, "hStdError");
391 if (PyErr_Occurred())
394 if (env_mapping
== Py_None
)
397 environment
= getenvironment(env_mapping
);
402 Py_BEGIN_ALLOW_THREADS
403 result
= CreateProcess(application_name
,
409 environment
? PyString_AS_STRING(environment
) : NULL
,
415 Py_XDECREF(environment
);
418 return PyErr_SetFromWindowsErr(GetLastError());
420 return Py_BuildValue("NNii",
421 sp_handle_new(pi
.hProcess
),
422 sp_handle_new(pi
.hThread
),
428 sp_TerminateProcess(PyObject
* self
, PyObject
* args
)
434 if (! PyArg_ParseTuple(args
, "li:TerminateProcess", &process
,
438 result
= TerminateProcess((HANDLE
) process
, exit_code
);
441 return PyErr_SetFromWindowsErr(GetLastError());
448 sp_GetExitCodeProcess(PyObject
* self
, PyObject
* args
)
454 if (! PyArg_ParseTuple(args
, "l:GetExitCodeProcess", &process
))
457 result
= GetExitCodeProcess((HANDLE
) process
, &exit_code
);
460 return PyErr_SetFromWindowsErr(GetLastError());
462 return PyInt_FromLong(exit_code
);
466 sp_WaitForSingleObject(PyObject
* self
, PyObject
* args
)
472 if (! PyArg_ParseTuple(args
, "li:WaitForSingleObject",
477 Py_BEGIN_ALLOW_THREADS
478 result
= WaitForSingleObject((HANDLE
) handle
, (DWORD
) milliseconds
);
481 if (result
== WAIT_FAILED
)
482 return PyErr_SetFromWindowsErr(GetLastError());
484 return PyInt_FromLong((int) result
);
488 sp_GetVersion(PyObject
* self
, PyObject
* args
)
490 if (! PyArg_ParseTuple(args
, ":GetVersion"))
493 return PyInt_FromLong((int) GetVersion());
497 sp_GetModuleFileName(PyObject
* self
, PyObject
* args
)
501 TCHAR filename
[MAX_PATH
];
503 if (! PyArg_ParseTuple(args
, "l:GetModuleFileName", &module
))
506 result
= GetModuleFileName((HMODULE
)module
, filename
, MAX_PATH
);
507 filename
[MAX_PATH
-1] = '\0';
510 return PyErr_SetFromWindowsErr(GetLastError());
512 return PyString_FromString(filename
);
515 static PyMethodDef sp_functions
[] = {
516 {"GetStdHandle", sp_GetStdHandle
, METH_VARARGS
},
517 {"GetCurrentProcess", sp_GetCurrentProcess
, METH_VARARGS
},
518 {"DuplicateHandle", sp_DuplicateHandle
, METH_VARARGS
},
519 {"CreatePipe", sp_CreatePipe
, METH_VARARGS
},
520 {"CreateProcess", sp_CreateProcess
, METH_VARARGS
},
521 {"TerminateProcess", sp_TerminateProcess
, METH_VARARGS
},
522 {"GetExitCodeProcess", sp_GetExitCodeProcess
, METH_VARARGS
},
523 {"WaitForSingleObject", sp_WaitForSingleObject
, METH_VARARGS
},
524 {"GetVersion", sp_GetVersion
, METH_VARARGS
},
525 {"GetModuleFileName", sp_GetModuleFileName
, METH_VARARGS
},
529 /* -------------------------------------------------------------------- */
532 defint(PyObject
* d
, const char* name
, int value
)
534 PyObject
* v
= PyInt_FromLong((long) value
);
536 PyDict_SetItemString(d
, (char*) name
, v
);
541 #if PY_VERSION_HEX >= 0x02030000
551 /* patch up object descriptors */
552 sp_handle_type
.ob_type
= &PyType_Type
;
553 sp_handle_as_number
.nb_int
= (unaryfunc
) sp_handle_as_int
;
555 m
= Py_InitModule("_subprocess", sp_functions
);
558 d
= PyModule_GetDict(m
);
561 defint(d
, "STD_INPUT_HANDLE", STD_INPUT_HANDLE
);
562 defint(d
, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE
);
563 defint(d
, "STD_ERROR_HANDLE", STD_ERROR_HANDLE
);
564 defint(d
, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS
);
565 defint(d
, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES
);
566 defint(d
, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW
);
567 defint(d
, "SW_HIDE", SW_HIDE
);
568 defint(d
, "INFINITE", INFINITE
);
569 defint(d
, "WAIT_OBJECT_0", WAIT_OBJECT_0
);
570 defint(d
, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE
);