1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * pyglib - Python bindings for GLib toolkit.
3 * Copyright (C) 1998-2003 James Henstridge
4 * 2004-2008 Johan Dahlin
6 * pygspawn.c: wrapper for the glib library.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
28 #include "pyglib-private.h"
30 struct _PyGChildSetupData {
35 PYGLIB_DEFINE_TYPE("gi._glib.Pid", PyGPid_Type, PYGLIB_PyLongObject)
38 pyg_pid_close(PyObject *self, PyObject *args, PyObject *kwargs)
40 g_spawn_close_pid(PYGLIB_PyLong_AsLong(self));
45 static PyMethodDef pyg_pid_methods[] = {
46 { "close", (PyCFunction)pyg_pid_close, METH_NOARGS },
51 pyg_pid_free(PyObject *gpid)
53 g_spawn_close_pid((GPid) PYGLIB_PyLong_AsLong(gpid));
54 PYGLIB_PyLong_Type.tp_free((void *) gpid);
58 pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs)
60 PyErr_SetString(PyExc_TypeError, "gi._glib.Pid cannot be manually instantiated");
67 PYGLIB_PyLongObject *pygpid;
69 #if PY_VERSION_HEX >= 0x03000000
70 return PyObject_CallMethod((PyObject*)&PyGPid_Type, "__new__", "Oi",
73 pygpid = PyObject_NEW(PyIntObject, &PyGPid_Type);
74 pygpid->ob_ival = pid;
76 return (PyObject *) pygpid;
80 _pyg_spawn_async_callback(gpointer user_data)
82 struct _PyGChildSetupData *data;
86 data = (struct _PyGChildSetupData *) user_data;
87 gil = pyglib_gil_state_ensure();
89 retval = PyObject_CallFunction(data->func, "O", data->data);
91 retval = PyObject_CallFunction(data->func, NULL);
96 Py_DECREF(data->func);
97 Py_XDECREF(data->data);
98 g_slice_free(struct _PyGChildSetupData, data);
99 pyglib_gil_state_release(gil);
103 pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
105 static char *kwlist[] = { "argv", "envp", "working_directory", "flags",
106 "child_setup", "user_data", "standard_input",
107 "standard_output", "standard_error", NULL };
108 PyObject *pyargv, *pyenvp = NULL;
109 char **argv, **envp = NULL;
110 PyObject *func = Py_None, *user_data = NULL;
111 char *working_directory = NULL;
112 int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1;
113 PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL;
114 gint *standard_input, *standard_output, *standard_error;
115 struct _PyGChildSetupData *callback_data = NULL;
116 GError *error = NULL;
120 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:gi._glib.spawn_async",
122 &pyargv, &pyenvp, &working_directory, &flags,
124 &pystdin, &pystdout, &pystderr))
127 if (pystdin && PyObject_IsTrue(pystdin))
128 standard_input = &_stdin;
130 standard_input = NULL;
132 if (pystdout && PyObject_IsTrue(pystdout))
133 standard_output = &_stdout;
135 standard_output = NULL;
137 if (pystderr && PyObject_IsTrue(pystderr))
138 standard_error = &_stderr;
140 standard_error = NULL;
143 if (!PySequence_Check(pyargv)) {
144 PyErr_SetString(PyExc_TypeError,
145 "gi._glib.spawn_async: "
146 "first argument must be a sequence of strings");
149 len = PySequence_Length(pyargv);
150 argv = g_new0(char *, len + 1);
151 for (i = 0; i < len; ++i) {
152 PyObject *tmp = PySequence_ITEM(pyargv, i);
153 if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
154 PyErr_SetString(PyExc_TypeError,
155 "gi._glib.spawn_async: "
156 "first argument must be a sequence of strings");
161 argv[i] = PYGLIB_PyUnicode_AsString(tmp);
167 if (!PySequence_Check(pyenvp)) {
168 PyErr_SetString(PyExc_TypeError,
169 "gi._glib.spawn_async: "
170 "second argument must be a sequence of strings");
174 len = PySequence_Length(pyenvp);
175 envp = g_new0(char *, len + 1);
176 for (i = 0; i < len; ++i) {
177 PyObject *tmp = PySequence_ITEM(pyenvp, i);
178 if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
179 PyErr_SetString(PyExc_TypeError,
180 "gi._glib.spawn_async: "
181 "second argument must be a sequence of strings");
187 envp[i] = PYGLIB_PyUnicode_AsString(tmp);
192 if (func != Py_None) {
193 if (!PyCallable_Check(func)) {
194 PyErr_SetString(PyExc_TypeError, "child_setup parameter must be callable or None");
200 callback_data = g_slice_new(struct _PyGChildSetupData);
201 callback_data->func = func;
202 callback_data->data = user_data;
203 Py_INCREF(callback_data->func);
204 if (callback_data->data)
205 Py_INCREF(callback_data->data);
208 if (!g_spawn_async_with_pipes(working_directory, argv, envp, flags,
209 (func != Py_None ? _pyg_spawn_async_callback : NULL),
210 callback_data, &child_pid,
219 if (envp) g_free(envp);
221 Py_DECREF(callback_data->func);
222 Py_XDECREF(callback_data->data);
223 g_slice_free(struct _PyGChildSetupData, callback_data);
225 pyglib_error_check(&error);
229 if (envp) g_free(envp);
232 pystdin = PYGLIB_PyLong_FromLong(*standard_input);
239 pystdout = PYGLIB_PyLong_FromLong(*standard_output);
246 pystderr = PYGLIB_PyLong_FromLong(*standard_error);
252 return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr);
256 pyglib_spawn_register_types(PyObject *d)
258 PyGPid_Type.tp_base = &PYGLIB_PyLong_Type;
259 PyGPid_Type.tp_flags = Py_TPFLAGS_DEFAULT;
260 PyGPid_Type.tp_methods = pyg_pid_methods;
261 PyGPid_Type.tp_init = pyg_pid_tp_init;
262 PyGPid_Type.tp_free = (freefunc)pyg_pid_free;
263 PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid");