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
;
72 #if defined(MS_WIN32) && !defined(MS_WIN64)
73 #define HANDLE_TO_PYNUM(handle) PyInt_FromLong((long) handle)
74 #define PY_HANDLE_PARAM "l"
76 #define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
77 #define PY_HANDLE_PARAM "L"
81 sp_handle_detach(sp_handle_object
* self
, PyObject
* args
)
85 if (! PyArg_ParseTuple(args
, ":Detach"))
88 handle
= self
->handle
;
90 self
->handle
= INVALID_HANDLE_VALUE
;
92 /* note: return the current handle, as an integer */
93 return HANDLE_TO_PYNUM(handle
);
97 sp_handle_close(sp_handle_object
* self
, PyObject
* args
)
99 if (! PyArg_ParseTuple(args
, ":Close"))
102 if (self
->handle
!= INVALID_HANDLE_VALUE
) {
103 CloseHandle(self
->handle
);
104 self
->handle
= INVALID_HANDLE_VALUE
;
111 sp_handle_dealloc(sp_handle_object
* self
)
113 if (self
->handle
!= INVALID_HANDLE_VALUE
)
114 CloseHandle(self
->handle
);
118 static PyMethodDef sp_handle_methods
[] = {
119 {"Detach", (PyCFunction
) sp_handle_detach
, METH_VARARGS
},
120 {"Close", (PyCFunction
) sp_handle_close
, METH_VARARGS
},
125 sp_handle_getattr(sp_handle_object
* self
, char* name
)
127 return Py_FindMethod(sp_handle_methods
, (PyObject
*) self
, name
);
131 sp_handle_as_int(sp_handle_object
* self
)
133 return HANDLE_TO_PYNUM(self
->handle
);
136 static PyNumberMethods sp_handle_as_number
;
138 statichere PyTypeObject sp_handle_type
= {
139 PyObject_HEAD_INIT(NULL
)
141 "_subprocess_handle", sizeof(sp_handle_object
), 0,
142 (destructor
) sp_handle_dealloc
, /*tp_dealloc*/
144 (getattrfunc
) sp_handle_getattr
,/*tp_getattr*/
148 &sp_handle_as_number
, /*tp_as_number */
149 0, /*tp_as_sequence */
150 0, /*tp_as_mapping */
154 /* -------------------------------------------------------------------- */
155 /* windows API functions */
158 sp_GetStdHandle(PyObject
* self
, PyObject
* args
)
163 if (! PyArg_ParseTuple(args
, "i:GetStdHandle", &std_handle
))
166 Py_BEGIN_ALLOW_THREADS
167 handle
= GetStdHandle((DWORD
) std_handle
);
170 if (handle
== INVALID_HANDLE_VALUE
)
171 return PyErr_SetFromWindowsErr(GetLastError());
178 /* note: returns integer, not handle object */
179 return HANDLE_TO_PYNUM(handle
);
183 sp_GetCurrentProcess(PyObject
* self
, PyObject
* args
)
185 if (! PyArg_ParseTuple(args
, ":GetCurrentProcess"))
188 return sp_handle_new(GetCurrentProcess());
192 sp_DuplicateHandle(PyObject
* self
, PyObject
* args
)
194 HANDLE target_handle
;
197 HANDLE source_process_handle
;
198 HANDLE source_handle
;
199 HANDLE target_process_handle
;
204 if (! PyArg_ParseTuple(args
,
205 PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM
206 "ii|i:DuplicateHandle",
207 &source_process_handle
,
209 &target_process_handle
,
215 Py_BEGIN_ALLOW_THREADS
216 result
= DuplicateHandle(
217 source_process_handle
,
219 target_process_handle
,
228 return PyErr_SetFromWindowsErr(GetLastError());
230 return sp_handle_new(target_handle
);
234 sp_CreatePipe(PyObject
* self
, PyObject
* args
)
240 PyObject
* pipe_attributes
; /* ignored */
243 if (! PyArg_ParseTuple(args
, "Oi:CreatePipe", &pipe_attributes
, &size
))
246 Py_BEGIN_ALLOW_THREADS
247 result
= CreatePipe(&read_pipe
, &write_pipe
, NULL
, size
);
251 return PyErr_SetFromWindowsErr(GetLastError());
253 return Py_BuildValue(
254 "NN", sp_handle_new(read_pipe
), sp_handle_new(write_pipe
));
257 /* helpers for createprocess */
260 getint(PyObject
* obj
, char* name
)
265 value
= PyObject_GetAttrString(obj
, name
);
267 PyErr_Clear(); /* FIXME: propagate error? */
270 ret
= (int) PyInt_AsLong(value
);
276 gethandle(PyObject
* obj
, char* name
)
278 sp_handle_object
* value
;
281 value
= (sp_handle_object
*) PyObject_GetAttrString(obj
, name
);
283 PyErr_Clear(); /* FIXME: propagate error? */
286 if (value
->ob_type
!= &sp_handle_type
)
295 getenvironment(PyObject
* environment
)
298 PyObject
* out
= NULL
;
303 /* convert environment dictionary to windows enviroment string */
304 if (! PyMapping_Check(environment
)) {
306 PyExc_TypeError
, "environment must be dictionary or None");
310 envsize
= PyMapping_Length(environment
);
312 keys
= PyMapping_Keys(environment
);
313 values
= PyMapping_Values(environment
);
314 if (!keys
|| !values
)
317 out
= PyString_FromStringAndSize(NULL
, 2048);
321 p
= PyString_AS_STRING(out
);
323 for (i
= 0; i
< envsize
; i
++) {
324 int ksize
, vsize
, totalsize
;
325 PyObject
* key
= PyList_GET_ITEM(keys
, i
);
326 PyObject
* value
= PyList_GET_ITEM(values
, i
);
328 if (! PyString_Check(key
) || ! PyString_Check(value
)) {
329 PyErr_SetString(PyExc_TypeError
,
330 "environment can only contain strings");
333 ksize
= PyString_GET_SIZE(key
);
334 vsize
= PyString_GET_SIZE(value
);
335 totalsize
= (p
- PyString_AS_STRING(out
)) + ksize
+ 1 +
337 if (totalsize
> PyString_GET_SIZE(out
)) {
338 int offset
= p
- PyString_AS_STRING(out
);
339 _PyString_Resize(&out
, totalsize
+ 1024);
340 p
= PyString_AS_STRING(out
) + offset
;
342 memcpy(p
, PyString_AS_STRING(key
), ksize
);
345 memcpy(p
, PyString_AS_STRING(value
), vsize
);
350 /* add trailing null byte */
352 _PyString_Resize(&out
, p
- PyString_AS_STRING(out
));
354 /* PyObject_Print(out, stdout, 0); */
369 sp_CreateProcess(PyObject
* self
, PyObject
* args
)
372 PROCESS_INFORMATION pi
;
374 PyObject
* environment
;
376 char* application_name
;
378 PyObject
* process_attributes
; /* ignored */
379 PyObject
* thread_attributes
; /* ignored */
382 PyObject
* env_mapping
;
383 char* current_directory
;
384 PyObject
* startup_info
;
386 if (! PyArg_ParseTuple(args
, "zzOOiiOzO:CreateProcess",
398 ZeroMemory(&si
, sizeof(si
));
401 /* note: we only support a small subset of all SI attributes */
402 si
.dwFlags
= getint(startup_info
, "dwFlags");
403 si
.wShowWindow
= getint(startup_info
, "wShowWindow");
404 si
.hStdInput
= gethandle(startup_info
, "hStdInput");
405 si
.hStdOutput
= gethandle(startup_info
, "hStdOutput");
406 si
.hStdError
= gethandle(startup_info
, "hStdError");
408 if (PyErr_Occurred())
411 if (env_mapping
== Py_None
)
414 environment
= getenvironment(env_mapping
);
419 Py_BEGIN_ALLOW_THREADS
420 result
= CreateProcess(application_name
,
426 environment
? PyString_AS_STRING(environment
) : NULL
,
432 Py_XDECREF(environment
);
435 return PyErr_SetFromWindowsErr(GetLastError());
437 return Py_BuildValue("NNii",
438 sp_handle_new(pi
.hProcess
),
439 sp_handle_new(pi
.hThread
),
445 sp_TerminateProcess(PyObject
* self
, PyObject
* args
)
451 if (! PyArg_ParseTuple(args
, PY_HANDLE_PARAM
"i:TerminateProcess",
452 &process
, &exit_code
))
455 result
= TerminateProcess(process
, exit_code
);
458 return PyErr_SetFromWindowsErr(GetLastError());
465 sp_GetExitCodeProcess(PyObject
* self
, PyObject
* args
)
471 if (! PyArg_ParseTuple(args
, PY_HANDLE_PARAM
":GetExitCodeProcess", &process
))
474 result
= GetExitCodeProcess(process
, &exit_code
);
477 return PyErr_SetFromWindowsErr(GetLastError());
479 return PyInt_FromLong(exit_code
);
483 sp_WaitForSingleObject(PyObject
* self
, PyObject
* args
)
489 if (! PyArg_ParseTuple(args
, PY_HANDLE_PARAM
"i:WaitForSingleObject",
494 Py_BEGIN_ALLOW_THREADS
495 result
= WaitForSingleObject(handle
, (DWORD
) milliseconds
);
498 if (result
== WAIT_FAILED
)
499 return PyErr_SetFromWindowsErr(GetLastError());
501 return PyInt_FromLong((int) result
);
505 sp_GetVersion(PyObject
* self
, PyObject
* args
)
507 if (! PyArg_ParseTuple(args
, ":GetVersion"))
510 return PyInt_FromLong((int) GetVersion());
514 sp_GetModuleFileName(PyObject
* self
, PyObject
* args
)
518 TCHAR filename
[MAX_PATH
];
520 if (! PyArg_ParseTuple(args
, PY_HANDLE_PARAM
":GetModuleFileName",
524 result
= GetModuleFileName(module
, filename
, MAX_PATH
);
525 filename
[MAX_PATH
-1] = '\0';
528 return PyErr_SetFromWindowsErr(GetLastError());
530 return PyString_FromString(filename
);
533 static PyMethodDef sp_functions
[] = {
534 {"GetStdHandle", sp_GetStdHandle
, METH_VARARGS
},
535 {"GetCurrentProcess", sp_GetCurrentProcess
, METH_VARARGS
},
536 {"DuplicateHandle", sp_DuplicateHandle
, METH_VARARGS
},
537 {"CreatePipe", sp_CreatePipe
, METH_VARARGS
},
538 {"CreateProcess", sp_CreateProcess
, METH_VARARGS
},
539 {"TerminateProcess", sp_TerminateProcess
, METH_VARARGS
},
540 {"GetExitCodeProcess", sp_GetExitCodeProcess
, METH_VARARGS
},
541 {"WaitForSingleObject", sp_WaitForSingleObject
, METH_VARARGS
},
542 {"GetVersion", sp_GetVersion
, METH_VARARGS
},
543 {"GetModuleFileName", sp_GetModuleFileName
, METH_VARARGS
},
547 /* -------------------------------------------------------------------- */
550 defint(PyObject
* d
, const char* name
, int value
)
552 PyObject
* v
= PyInt_FromLong((long) value
);
554 PyDict_SetItemString(d
, (char*) name
, v
);
559 #if PY_VERSION_HEX >= 0x02030000
569 /* patch up object descriptors */
570 sp_handle_type
.ob_type
= &PyType_Type
;
571 sp_handle_as_number
.nb_int
= (unaryfunc
) sp_handle_as_int
;
573 m
= Py_InitModule("_subprocess", sp_functions
);
576 d
= PyModule_GetDict(m
);
579 defint(d
, "STD_INPUT_HANDLE", STD_INPUT_HANDLE
);
580 defint(d
, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE
);
581 defint(d
, "STD_ERROR_HANDLE", STD_ERROR_HANDLE
);
582 defint(d
, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS
);
583 defint(d
, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES
);
584 defint(d
, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW
);
585 defint(d
, "SW_HIDE", SW_HIDE
);
586 defint(d
, "INFINITE", INFINITE
);
587 defint(d
, "WAIT_OBJECT_0", WAIT_OBJECT_0
);
588 defint(d
, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE
);