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"
32 struct _PyGChildSetupData {
37 PYGLIB_DEFINE_TYPE("gi._glib.Pid", PyGPid_Type, PYGLIB_PyLongObject)
40 pyg_pid_close(PyObject *self, PyObject *args, PyObject *kwargs)
42 g_spawn_close_pid(PYGLIB_PyLong_AsLong(self));
47 static PyMethodDef pyg_pid_methods[] = {
48 { "close", (PyCFunction)pyg_pid_close, METH_NOARGS },
53 pyg_pid_free(PyObject *gpid)
55 g_spawn_close_pid((GPid) PYGLIB_PyLong_AsLong(gpid));
56 PYGLIB_PyLong_Type.tp_free((void *) gpid);
60 pyg_pid_tp_init(PyObject *self, PyObject *args, PyObject *kwargs)
62 PyErr_SetString(PyExc_TypeError, "gi._glib.Pid cannot be manually instantiated");
69 return PyObject_CallMethod((PyObject*)&PyGPid_Type, "__new__", "Oi",
74 _pyg_spawn_async_callback(gpointer user_data)
76 struct _PyGChildSetupData *data;
80 data = (struct _PyGChildSetupData *) user_data;
81 gil = pyglib_gil_state_ensure();
83 retval = PyObject_CallFunction(data->func, "O", data->data);
85 retval = PyObject_CallFunction(data->func, NULL);
90 Py_DECREF(data->func);
91 Py_XDECREF(data->data);
92 g_slice_free(struct _PyGChildSetupData, data);
93 pyglib_gil_state_release(gil);
97 pyglib_spawn_async(PyObject *object, PyObject *args, PyObject *kwargs)
99 static char *kwlist[] = { "argv", "envp", "working_directory", "flags",
100 "child_setup", "user_data", "standard_input",
101 "standard_output", "standard_error", NULL };
102 PyObject *pyargv, *pyenvp = NULL;
103 char **argv, **envp = NULL;
104 PyObject *func = Py_None, *user_data = NULL;
105 char *working_directory = NULL;
106 int flags = 0, _stdin = -1, _stdout = -1, _stderr = -1;
107 PyObject *pystdin = NULL, *pystdout = NULL, *pystderr = NULL;
108 gint *standard_input, *standard_output, *standard_error;
109 struct _PyGChildSetupData *callback_data = NULL;
110 GError *error = NULL;
114 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OsiOOOOO:gi._glib.spawn_async",
116 &pyargv, &pyenvp, &working_directory, &flags,
118 &pystdin, &pystdout, &pystderr))
121 if (pystdin && PyObject_IsTrue(pystdin))
122 standard_input = &_stdin;
124 standard_input = NULL;
126 if (pystdout && PyObject_IsTrue(pystdout))
127 standard_output = &_stdout;
129 standard_output = NULL;
131 if (pystderr && PyObject_IsTrue(pystderr))
132 standard_error = &_stderr;
134 standard_error = NULL;
137 if (!PySequence_Check(pyargv)) {
138 PyErr_SetString(PyExc_TypeError,
139 "gi._glib.spawn_async: "
140 "first argument must be a sequence of strings");
143 len = PySequence_Length(pyargv);
144 argv = g_new0(char *, len + 1);
145 for (i = 0; i < len; ++i) {
146 PyObject *tmp = PySequence_ITEM(pyargv, i);
147 if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
148 PyErr_SetString(PyExc_TypeError,
149 "gi._glib.spawn_async: "
150 "first argument must be a sequence of strings");
155 argv[i] = PYGLIB_PyUnicode_AsString(tmp);
161 if (!PySequence_Check(pyenvp)) {
162 PyErr_SetString(PyExc_TypeError,
163 "gi._glib.spawn_async: "
164 "second argument must be a sequence of strings");
168 len = PySequence_Length(pyenvp);
169 envp = g_new0(char *, len + 1);
170 for (i = 0; i < len; ++i) {
171 PyObject *tmp = PySequence_ITEM(pyenvp, i);
172 if (tmp == NULL || !PYGLIB_PyUnicode_Check(tmp)) {
173 PyErr_SetString(PyExc_TypeError,
174 "gi._glib.spawn_async: "
175 "second argument must be a sequence of strings");
181 envp[i] = PYGLIB_PyUnicode_AsString(tmp);
186 if (func != Py_None) {
187 if (!PyCallable_Check(func)) {
188 PyErr_SetString(PyExc_TypeError, "child_setup parameter must be callable or None");
194 callback_data = g_slice_new(struct _PyGChildSetupData);
195 callback_data->func = func;
196 callback_data->data = user_data;
197 Py_INCREF(callback_data->func);
198 if (callback_data->data)
199 Py_INCREF(callback_data->data);
202 if (!g_spawn_async_with_pipes(working_directory, argv, envp, flags,
203 (func != Py_None ? _pyg_spawn_async_callback : NULL),
204 callback_data, &child_pid,
213 if (envp) g_free(envp);
215 Py_DECREF(callback_data->func);
216 Py_XDECREF(callback_data->data);
217 g_slice_free(struct _PyGChildSetupData, callback_data);
219 pyglib_error_check(&error);
223 if (envp) g_free(envp);
226 pystdin = PYGLIB_PyLong_FromLong(*standard_input);
233 pystdout = PYGLIB_PyLong_FromLong(*standard_output);
240 pystderr = PYGLIB_PyLong_FromLong(*standard_error);
246 return Py_BuildValue("NNNN", pyg_pid_new(child_pid), pystdin, pystdout, pystderr);
250 pyglib_spawn_register_types(PyObject *d)
252 PyGPid_Type.tp_base = &PYGLIB_PyLong_Type;
253 PyGPid_Type.tp_flags = Py_TPFLAGS_DEFAULT;
254 PyGPid_Type.tp_methods = pyg_pid_methods;
255 PyGPid_Type.tp_init = pyg_pid_tp_init;
256 PyGPid_Type.tp_free = (freefunc)pyg_pid_free;
257 PyGPid_Type.tp_new = PYGLIB_PyLong_Type.tp_new;
258 PYGLIB_REGISTER_TYPE(d, PyGPid_Type, "Pid");