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, see <http://www.gnu.org/licenses/>.
25 #include "pygi-python-compat.h"
26 #include "pygi-basictype.h"
28 #include "pygi-error.h"
30 struct _PyGChildSetupData
{
35 PYGLIB_DEFINE_TYPE("gi._gi.Pid", PyGPid_Type
, PYGLIB_PyLongObject
)
38 pyg_pid_get_pid (PyObject
*self
)
41 return (GPid
)PyLong_AsVoidPtr (self
);
43 return (GPid
)PYGLIB_PyLong_AsLong (self
);
48 pyg_pid_close(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
50 g_spawn_close_pid(pyg_pid_get_pid (self
));
55 static PyMethodDef pyg_pid_methods
[] = {
56 { "close", (PyCFunction
)pyg_pid_close
, METH_NOARGS
},
61 pyg_pid_free(PyObject
*gpid
)
63 g_spawn_close_pid(pyg_pid_get_pid (gpid
));
64 PYGLIB_PyLong_Type
.tp_free((void *) gpid
);
68 pyg_pid_tp_init(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
70 PyErr_SetString(PyExc_TypeError
, "gi._gi.Pid cannot be manually instantiated");
79 long_val
= PyLong_FromVoidPtr (pid
);
81 long_val
= pygi_gint_to_py (pid
);
83 return PyObject_CallMethod((PyObject
*)&PyGPid_Type
, "__new__", "ON",
84 &PyGPid_Type
, long_val
);
88 _pyg_spawn_async_callback(gpointer user_data
)
90 struct _PyGChildSetupData
*data
;
94 data
= (struct _PyGChildSetupData
*) user_data
;
95 gil
= PyGILState_Ensure();
97 retval
= PyObject_CallFunction(data
->func
, "O", data
->data
);
99 retval
= PyObject_CallFunction(data
->func
, NULL
);
104 Py_DECREF(data
->func
);
105 Py_XDECREF(data
->data
);
106 g_slice_free(struct _PyGChildSetupData
, data
);
107 PyGILState_Release(gil
);
111 pyglib_spawn_async(PyObject
*object
, PyObject
*args
, PyObject
*kwargs
)
113 static char *kwlist
[] = { "argv", "envp", "working_directory", "flags",
114 "child_setup", "user_data", "standard_input",
115 "standard_output", "standard_error", NULL
};
116 PyObject
*pyargv
, *pyenvp
= NULL
;
117 char **argv
, **envp
= NULL
;
118 PyObject
*func
= Py_None
, *user_data
= NULL
;
119 char *working_directory
= NULL
;
120 int flags
= 0, _stdin
= -1, _stdout
= -1, _stderr
= -1;
121 PyObject
*pystdin
= NULL
, *pystdout
= NULL
, *pystderr
= NULL
;
122 gint
*standard_input
, *standard_output
, *standard_error
;
123 struct _PyGChildSetupData
*callback_data
= NULL
;
124 GError
*error
= NULL
;
128 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OsiOOOOO:gi._gi.spawn_async",
130 &pyargv
, &pyenvp
, &working_directory
, &flags
,
132 &pystdin
, &pystdout
, &pystderr
))
135 if (pystdin
&& PyObject_IsTrue(pystdin
))
136 standard_input
= &_stdin
;
138 standard_input
= NULL
;
140 if (pystdout
&& PyObject_IsTrue(pystdout
))
141 standard_output
= &_stdout
;
143 standard_output
= NULL
;
145 if (pystderr
&& PyObject_IsTrue(pystderr
))
146 standard_error
= &_stderr
;
148 standard_error
= NULL
;
151 if (!PySequence_Check(pyargv
)) {
152 PyErr_SetString(PyExc_TypeError
,
153 "gi._gi.spawn_async: "
154 "first argument must be a sequence of strings");
157 len
= PySequence_Length(pyargv
);
158 argv
= g_new0(char *, len
+ 1);
159 for (i
= 0; i
< len
; ++i
) {
160 PyObject
*tmp
= PySequence_ITEM(pyargv
, i
);
161 if (tmp
== NULL
|| !PYGLIB_PyUnicode_Check(tmp
)) {
162 PyErr_SetString(PyExc_TypeError
,
163 "gi._gi.spawn_async: "
164 "first argument must be a sequence of strings");
169 argv
[i
] = PYGLIB_PyUnicode_AsString(tmp
);
175 if (!PySequence_Check(pyenvp
)) {
176 PyErr_SetString(PyExc_TypeError
,
177 "gi._gi.spawn_async: "
178 "second argument must be a sequence of strings");
182 len
= PySequence_Length(pyenvp
);
183 envp
= g_new0(char *, len
+ 1);
184 for (i
= 0; i
< len
; ++i
) {
185 PyObject
*tmp
= PySequence_ITEM(pyenvp
, i
);
186 if (tmp
== NULL
|| !PYGLIB_PyUnicode_Check(tmp
)) {
187 PyErr_SetString(PyExc_TypeError
,
188 "gi._gi.spawn_async: "
189 "second argument must be a sequence of strings");
195 envp
[i
] = PYGLIB_PyUnicode_AsString(tmp
);
200 if (func
!= Py_None
) {
201 if (!PyCallable_Check(func
)) {
202 PyErr_SetString(PyExc_TypeError
, "child_setup parameter must be callable or None");
208 callback_data
= g_slice_new(struct _PyGChildSetupData
);
209 callback_data
->func
= func
;
210 callback_data
->data
= user_data
;
211 Py_INCREF(callback_data
->func
);
212 if (callback_data
->data
)
213 Py_INCREF(callback_data
->data
);
216 if (!g_spawn_async_with_pipes(working_directory
, argv
, envp
, flags
,
217 (func
!= Py_None
? _pyg_spawn_async_callback
: NULL
),
218 callback_data
, &child_pid
,
227 if (envp
) g_free(envp
);
229 Py_DECREF(callback_data
->func
);
230 Py_XDECREF(callback_data
->data
);
231 g_slice_free(struct _PyGChildSetupData
, callback_data
);
233 pygi_error_check(&error
);
237 if (envp
) g_free(envp
);
240 pystdin
= pygi_gint_to_py(*standard_input
);
247 pystdout
= pygi_gint_to_py(*standard_output
);
254 pystderr
= pygi_gint_to_py(*standard_error
);
260 return Py_BuildValue("NNNN", pyg_pid_new(child_pid
), pystdin
, pystdout
, pystderr
);
264 * Returns 0 on success, or -1 and sets an exception.
267 pygi_spawn_register_types(PyObject
*d
)
269 PyGPid_Type
.tp_base
= &PYGLIB_PyLong_Type
;
270 PyGPid_Type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
271 PyGPid_Type
.tp_methods
= pyg_pid_methods
;
272 PyGPid_Type
.tp_init
= pyg_pid_tp_init
;
273 PyGPid_Type
.tp_free
= (freefunc
)pyg_pid_free
;
274 PyGPid_Type
.tp_new
= PYGLIB_PyLong_Type
.tp_new
;
275 PYGLIB_REGISTER_TYPE(d
, PyGPid_Type
, "Pid");