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("glib.Pid", PyGPid_Type
, _PyLongObject
)
38 pyg_pid_close(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
40 g_spawn_close_pid(_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
) _PyLong_AsLong(gpid
));
54 _PyLong_Type
.tp_free((void *) gpid
);
58 pyg_pid_tp_init(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
60 PyErr_SetString(PyExc_TypeError
, "glib.Pid cannot be manually instantiated");
67 _PyLongObject
*pygpid
;
68 pygpid
= PyObject_NEW(_PyLongObject
, &PyGPid_Type
);
70 #if PY_VERSION_HEX >= 0x03000000
71 # warning "FIXME: figure out how to subclass long"
73 pygpid
->ob_ival
= pid
;
75 return (PyObject
*) pygpid
;
79 _pyg_spawn_async_callback(gpointer user_data
)
81 struct _PyGChildSetupData
*data
;
85 data
= (struct _PyGChildSetupData
*) user_data
;
86 gil
= pyglib_gil_state_ensure();
88 retval
= PyObject_CallFunction(data
->func
, "O", data
->data
);
90 retval
= PyObject_CallFunction(data
->func
, NULL
);
95 Py_DECREF(data
->func
);
96 Py_XDECREF(data
->data
);
97 g_slice_free(struct _PyGChildSetupData
, data
);
98 pyglib_gil_state_release(gil
);
102 pyglib_spawn_async(PyObject
*object
, PyObject
*args
, PyObject
*kwargs
)
104 static char *kwlist
[] = { "argv", "envp", "working_directory", "flags",
105 "child_setup", "user_data", "standard_input",
106 "standard_output", "standard_error", NULL
};
107 PyObject
*pyargv
, *pyenvp
= NULL
;
108 char **argv
, **envp
= NULL
;
109 PyObject
*func
= Py_None
, *user_data
= NULL
;
110 char *working_directory
= NULL
;
111 int flags
= 0, _stdin
= -1, _stdout
= -1, _stderr
= -1;
112 PyObject
*pystdin
= NULL
, *pystdout
= NULL
, *pystderr
= NULL
;
113 gint
*standard_input
, *standard_output
, *standard_error
;
114 struct _PyGChildSetupData
*callback_data
= NULL
;
115 GError
*error
= NULL
;
119 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OsiOOOOO:glib.spawn_async",
121 &pyargv
, &pyenvp
, &working_directory
, &flags
,
123 &pystdin
, &pystdout
, &pystderr
))
126 if (pystdin
&& PyObject_IsTrue(pystdin
))
127 standard_input
= &_stdin
;
129 standard_input
= NULL
;
131 if (pystdout
&& PyObject_IsTrue(pystdout
))
132 standard_output
= &_stdout
;
134 standard_output
= NULL
;
136 if (pystderr
&& PyObject_IsTrue(pystderr
))
137 standard_error
= &_stderr
;
139 standard_error
= NULL
;
142 if (!PySequence_Check(pyargv
)) {
143 PyErr_SetString(PyExc_TypeError
,
145 "first argument must be a sequence of strings");
148 len
= PySequence_Length(pyargv
);
149 argv
= g_new0(char *, len
+ 1);
150 for (i
= 0; i
< len
; ++i
) {
151 PyObject
*tmp
= PySequence_ITEM(pyargv
, i
);
152 if (!_PyUnicode_Check(tmp
)) {
153 PyErr_SetString(PyExc_TypeError
,
155 "first argument must be a sequence of strings");
160 argv
[i
] = _PyUnicode_AsString(tmp
);
166 if (!PySequence_Check(pyenvp
)) {
167 PyErr_SetString(PyExc_TypeError
,
169 "second argument must be a sequence of strings");
173 len
= PySequence_Length(pyenvp
);
174 envp
= g_new0(char *, len
+ 1);
175 for (i
= 0; i
< len
; ++i
) {
176 PyObject
*tmp
= PySequence_ITEM(pyenvp
, i
);
177 if (!_PyUnicode_Check(tmp
)) {
178 PyErr_SetString(PyExc_TypeError
,
180 "second argument must be a sequence of strings");
186 envp
[i
] = _PyUnicode_AsString(tmp
);
191 if (func
!= Py_None
) {
192 if (!PyCallable_Check(func
)) {
193 PyErr_SetString(PyExc_TypeError
, "child_setup parameter must be callable or None");
199 callback_data
= g_slice_new(struct _PyGChildSetupData
);
200 callback_data
->func
= func
;
201 callback_data
->data
= user_data
;
202 Py_INCREF(callback_data
->func
);
203 if (callback_data
->data
)
204 Py_INCREF(callback_data
->data
);
207 if (!g_spawn_async_with_pipes(working_directory
, argv
, envp
, flags
,
208 (func
!= Py_None
? _pyg_spawn_async_callback
: NULL
),
209 callback_data
, &child_pid
,
218 if (envp
) g_free(envp
);
220 Py_DECREF(callback_data
->func
);
221 Py_XDECREF(callback_data
->data
);
222 g_slice_free(struct _PyGChildSetupData
, callback_data
);
224 pyglib_error_check(&error
);
228 if (envp
) g_free(envp
);
231 pystdin
= _PyLong_FromLong(*standard_input
);
238 pystdout
= _PyLong_FromLong(*standard_output
);
245 pystderr
= _PyLong_FromLong(*standard_error
);
251 return Py_BuildValue("NNNN", pyg_pid_new(child_pid
), pystdin
, pystdout
, pystderr
);
255 pyglib_spawn_register_types(PyObject
*d
)
257 PyGPid_Type
.tp_base
= &_PyLong_Type
;
258 PyGPid_Type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
259 PyGPid_Type
.tp_methods
= pyg_pid_methods
;
260 PyGPid_Type
.tp_init
= pyg_pid_tp_init
;
261 PyGPid_Type
.tp_free
= (freefunc
)pyg_pid_free
;
262 PYGLIB_REGISTER_TYPE(d
, PyGPid_Type
, "Pid");