2 * Copyright (c) 2008-2009 Christian Hammond
3 * Copyright (c) 2008-2009 David Trowbridge
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "claws-features.h"
30 #include <pygobject.h>
31 #endif // ENABLE_PYTHON
34 #include <glib/gi18n.h>
40 #include "python-hooks.h"
43 static gboolean python_enabled
= FALSE
;
44 static void *python_dlhandle
= NULL
;
47 static GString
*captured_stdout
= NULL
;
48 static GString
*captured_stderr
= NULL
;
52 capture_stdout(PyObject
*self
, PyObject
*args
)
56 if (!PyArg_ParseTuple(args
, "s", &str
))
59 g_string_append(captured_stdout
, str
);
66 capture_stderr(PyObject
*self
, PyObject
*args
)
70 if (!PyArg_ParseTuple(args
, "s", &str
))
73 g_string_append(captured_stderr
, str
);
80 capture_stdin(PyObject
*self
, PyObject
*args
)
82 /* Return an empty string.
83 * This is what read() returns when hitting EOF. */
84 return PyUnicode_FromString("");
88 wrap_gobj(PyObject
*self
, PyObject
*args
)
93 if (!PyArg_ParseTuple(args
, "l", &addr
))
96 if (!G_IS_OBJECT(addr
))
104 return pygobject_new(obj
);
107 static PyMethodDef parasite_python_methods
[] = {
108 {"capture_stdout", capture_stdout
, METH_VARARGS
, "Captures stdout"},
109 {"capture_stderr", capture_stderr
, METH_VARARGS
, "Captures stderr"},
110 {"capture_stdin", capture_stdin
, METH_VARARGS
, "Captures stdin"},
111 {"gobj", wrap_gobj
, METH_VARARGS
, "Wraps a C GObject"},
112 {NULL
, NULL
, 0, NULL
}
119 const char *prgname
= g_get_prgname();
121 return (!strcmp(prgname
, "gimp"));
123 #endif // ENABLE_PYTHON
125 static struct PyModuleDef moduledef
= {
126 PyModuleDef_HEAD_INIT
,
130 parasite_python_methods
,
138 parasite_python_module_init(void)
141 return PyModule_Create(&moduledef
);
142 #endif // ENABLE_PYTHON
147 parasite_python_init(char **error
)
150 struct sigaction old_sigint
;
153 if (is_blacklisted()) {
154 *error
= g_strdup("Application is blacklisted");
158 /* This prevents errors such as "undefined symbol: PyExc_ImportError" */
159 python_dlhandle
= dlopen(PYTHON_SHARED_LIB
, RTLD_NOW
| RTLD_GLOBAL
);
160 if (python_dlhandle
== NULL
)
162 *error
= g_strdup_printf("Parasite: Error on dlopen(): %s\n", dlerror());
166 captured_stdout
= g_string_new("");
167 captured_stderr
= g_string_new("");
169 /* Back up and later restore SIGINT so Python doesn't steal it from us. */
170 sigaction(SIGINT
, NULL
, &old_sigint
);
172 if (!Py_IsInitialized())
175 sigaction(SIGINT
, &old_sigint
, NULL
);
177 if(PyRun_SimpleString(
181 "class StdoutCatcher:\n"
182 " def write(self, str):\n"
183 " parasite.capture_stdout(str)\n"
184 " def flush(self):\n"
187 "class StderrCatcher:\n"
188 " def write(self, str):\n"
189 " parasite.capture_stderr(str)\n"
190 " def flush(self):\n"
193 "class StdinCatcher:\n"
194 " def readline(self, size=-1):\n"
195 " return parasite.capture_stdin(size)\n"
196 " def read(self, size=-1):\n"
197 " return parasite.capture_stdin(size)\n"
198 " def flush(self):\n"
202 dlclose(python_dlhandle
);
203 python_dlhandle
= NULL
;
207 pygtk
= PyImport_ImportModule("gi");
211 *error
= g_strdup("Parasite: Could not import gi");
212 dlclose(python_dlhandle
);
213 python_dlhandle
= NULL
;
217 python_enabled
= TRUE
;
218 #endif // ENABLE_PYTHON
223 parasite_python_done(void)
226 if(python_dlhandle
!= NULL
) {
227 dlclose(python_dlhandle
);
228 python_dlhandle
= NULL
;
234 parasite_python_run(const char *command
,
235 ParasitePythonLogger stdout_logger
,
236 ParasitePythonLogger stderr_logger
,
240 PyGILState_STATE gstate
;
246 /* empty string as command is a noop */
247 if(!strcmp(command
, ""))
250 /* if first non-whitespace character is '#', command is also a noop */
252 while(cp
&& (*cp
!= '\0') && g_ascii_isspace(*cp
))
257 gstate
= PyGILState_Ensure();
259 module
= PyImport_AddModule("__main__");
260 dict
= PyModule_GetDict(module
);
262 PyRun_SimpleString("old_stdout = sys.stdout\n"
263 "old_stderr = sys.stderr\n"
264 "old_stdin = sys.stdin\n"
265 "sys.stdout = StdoutCatcher()\n"
266 "sys.stderr = StderrCatcher()\n"
267 "sys.stdin = StdinCatcher()\n");
269 obj
= PyRun_String(command
, Py_single_input
, dict
, dict
);
272 PyRun_SimpleString("sys.stdout = old_stdout\n"
273 "sys.stderr = old_stderr\n"
274 "sys.stdin = old_stdin\n");
276 if (stdout_logger
!= NULL
)
277 stdout_logger(captured_stdout
->str
, user_data
);
279 if (stderr_logger
!= NULL
)
280 stderr_logger(captured_stderr
->str
, user_data
);
282 // Print any returned object
283 if (obj
!= NULL
&& obj
!= Py_None
) {
284 PyObject
*repr
= PyObject_Repr(obj
);
286 char *string
= PyBytes_AsString(repr
);
288 if (stdout_logger
!= NULL
) {
289 stdout_logger(string
, user_data
);
290 stdout_logger("\n", user_data
);
298 PyGILState_Release(gstate
);
299 g_string_erase(captured_stdout
, 0, -1);
300 g_string_erase(captured_stderr
, 0, -1);
301 #endif // ENABLE_PYTHON
305 parasite_python_is_enabled(void)
307 return python_enabled
;
310 // vim: set et sw=4 ts=4: