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
, METH_VARARGS
},
112 {"Close", (PyCFunction
) sp_handle_close
, METH_VARARGS
},
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
)
255 value
= PyObject_GetAttrString(obj
, name
);
257 PyErr_Clear(); /* FIXME: propagate error? */
260 ret
= (int) PyInt_AsLong(value
);
266 gethandle(PyObject
* obj
, char* name
)
268 sp_handle_object
* value
;
271 value
= (sp_handle_object
*) PyObject_GetAttrString(obj
, name
);
273 PyErr_Clear(); /* FIXME: propagate error? */
276 if (value
->ob_type
!= &sp_handle_type
)
285 getenvironment(PyObject
* environment
)
288 PyObject
* out
= NULL
;
293 /* convert environment dictionary to windows enviroment string */
294 if (! PyMapping_Check(environment
)) {
296 PyExc_TypeError
, "environment must be dictionary or None");
300 envsize
= PyMapping_Length(environment
);
302 keys
= PyMapping_Keys(environment
);
303 values
= PyMapping_Values(environment
);
304 if (!keys
|| !values
)
307 out
= PyString_FromStringAndSize(NULL
, 2048);
311 p
= PyString_AS_STRING(out
);
313 for (i
= 0; i
< envsize
; i
++) {
314 int ksize
, vsize
, totalsize
;
315 PyObject
* key
= PyList_GET_ITEM(keys
, i
);
316 PyObject
* value
= PyList_GET_ITEM(values
, i
);
318 if (! PyString_Check(key
) || ! PyString_Check(value
)) {
319 PyErr_SetString(PyExc_TypeError
,
320 "environment can only contain strings");
323 ksize
= PyString_GET_SIZE(key
);
324 vsize
= PyString_GET_SIZE(value
);
325 totalsize
= (p
- PyString_AS_STRING(out
)) + ksize
+ 1 +
327 if (totalsize
> PyString_GET_SIZE(out
)) {
328 int offset
= p
- PyString_AS_STRING(out
);
329 _PyString_Resize(&out
, totalsize
+ 1024);
330 p
= PyString_AS_STRING(out
) + offset
;
332 memcpy(p
, PyString_AS_STRING(key
), ksize
);
335 memcpy(p
, PyString_AS_STRING(value
), vsize
);
340 /* add trailing null byte */
342 _PyString_Resize(&out
, p
- PyString_AS_STRING(out
));
344 /* PyObject_Print(out, stdout, 0); */
359 sp_CreateProcess(PyObject
* self
, PyObject
* args
)
362 PROCESS_INFORMATION pi
;
364 PyObject
* environment
;
366 char* application_name
;
368 PyObject
* process_attributes
; /* ignored */
369 PyObject
* thread_attributes
; /* ignored */
372 PyObject
* env_mapping
;
373 char* current_directory
;
374 PyObject
* startup_info
;
376 if (! PyArg_ParseTuple(args
, "zzOOiiOzO:CreateProcess",
388 ZeroMemory(&si
, sizeof(si
));
391 /* note: we only support a small subset of all SI attributes */
392 si
.dwFlags
= getint(startup_info
, "dwFlags");
393 si
.wShowWindow
= getint(startup_info
, "wShowWindow");
394 si
.hStdInput
= gethandle(startup_info
, "hStdInput");
395 si
.hStdOutput
= gethandle(startup_info
, "hStdOutput");
396 si
.hStdError
= gethandle(startup_info
, "hStdError");
398 if (PyErr_Occurred())
401 if (env_mapping
== Py_None
)
404 environment
= getenvironment(env_mapping
);
409 Py_BEGIN_ALLOW_THREADS
410 result
= CreateProcess(application_name
,
416 environment
? PyString_AS_STRING(environment
) : NULL
,
422 Py_XDECREF(environment
);
425 return PyErr_SetFromWindowsErr(GetLastError());
427 return Py_BuildValue("NNii",
428 sp_handle_new(pi
.hProcess
),
429 sp_handle_new(pi
.hThread
),
435 sp_TerminateProcess(PyObject
* self
, PyObject
* args
)
441 if (! PyArg_ParseTuple(args
, "li:TerminateProcess", &process
,
445 result
= TerminateProcess((HANDLE
) process
, exit_code
);
448 return PyErr_SetFromWindowsErr(GetLastError());
455 sp_GetExitCodeProcess(PyObject
* self
, PyObject
* args
)
461 if (! PyArg_ParseTuple(args
, "l:GetExitCodeProcess", &process
))
464 result
= GetExitCodeProcess((HANDLE
) process
, &exit_code
);
467 return PyErr_SetFromWindowsErr(GetLastError());
469 return PyInt_FromLong(exit_code
);
473 sp_WaitForSingleObject(PyObject
* self
, PyObject
* args
)
479 if (! PyArg_ParseTuple(args
, "li:WaitForSingleObject",
484 Py_BEGIN_ALLOW_THREADS
485 result
= WaitForSingleObject((HANDLE
) handle
, (DWORD
) milliseconds
);
488 if (result
== WAIT_FAILED
)
489 return PyErr_SetFromWindowsErr(GetLastError());
491 return PyInt_FromLong((int) result
);
495 sp_GetVersion(PyObject
* self
, PyObject
* args
)
497 if (! PyArg_ParseTuple(args
, ":GetVersion"))
500 return PyInt_FromLong((int) GetVersion());
504 sp_GetModuleFileName(PyObject
* self
, PyObject
* args
)
508 TCHAR filename
[MAX_PATH
];
510 if (! PyArg_ParseTuple(args
, "l:GetModuleFileName", &module
))
513 result
= GetModuleFileName((HMODULE
)module
, filename
, MAX_PATH
);
514 filename
[MAX_PATH
-1] = '\0';
517 return PyErr_SetFromWindowsErr(GetLastError());
519 return PyString_FromString(filename
);
522 static PyMethodDef sp_functions
[] = {
523 {"GetStdHandle", sp_GetStdHandle
, METH_VARARGS
},
524 {"GetCurrentProcess", sp_GetCurrentProcess
, METH_VARARGS
},
525 {"DuplicateHandle", sp_DuplicateHandle
, METH_VARARGS
},
526 {"CreatePipe", sp_CreatePipe
, METH_VARARGS
},
527 {"CreateProcess", sp_CreateProcess
, METH_VARARGS
},
528 {"TerminateProcess", sp_TerminateProcess
, METH_VARARGS
},
529 {"GetExitCodeProcess", sp_GetExitCodeProcess
, METH_VARARGS
},
530 {"WaitForSingleObject", sp_WaitForSingleObject
, METH_VARARGS
},
531 {"GetVersion", sp_GetVersion
, METH_VARARGS
},
532 {"GetModuleFileName", sp_GetModuleFileName
, METH_VARARGS
},
536 /* -------------------------------------------------------------------- */
539 defint(PyObject
* d
, const char* name
, int value
)
541 PyObject
* v
= PyInt_FromLong((long) value
);
543 PyDict_SetItemString(d
, (char*) name
, v
);
548 #if PY_VERSION_HEX >= 0x02030000
558 /* patch up object descriptors */
559 sp_handle_type
.ob_type
= &PyType_Type
;
560 sp_handle_as_number
.nb_int
= (unaryfunc
) sp_handle_as_int
;
562 m
= Py_InitModule("_subprocess", sp_functions
);
565 d
= PyModule_GetDict(m
);
568 defint(d
, "STD_INPUT_HANDLE", STD_INPUT_HANDLE
);
569 defint(d
, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE
);
570 defint(d
, "STD_ERROR_HANDLE", STD_ERROR_HANDLE
);
571 defint(d
, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS
);
572 defint(d
, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES
);
573 defint(d
, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW
);
574 defint(d
, "SW_HIDE", SW_HIDE
);
575 defint(d
, "INFINITE", INFINITE
);
576 defint(d
, "WAIT_OBJECT_0", WAIT_OBJECT_0
);
577 defint(d
, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE
);