return PyLong_FromLong(cmp);
}
-static int Pakfire_execute_output_callback(struct pakfire_ctx* ctx, struct pakfire_jail* jail,
- void* data, const char* line, size_t length) {
- PyObject* callback = (PyObject*)data;
- PyObject* args = NULL;
- PyObject* result = NULL;
- int r = 1;
-
- // Do nothing if callback isn't set
- if (!callback)
- return 0;
-
- // Remove the trailing newline
- if (line && length && line[length - 1] == '\n')
- length--;
-
- // Get the GIL
- PyGILState_STATE state = PyGILState_Ensure();
-
- // Create tuple with arguments for the callback function
- args = Py_BuildValue("(is#)", LOG_INFO, line, (Py_ssize_t)length);
- if (!args)
- goto ERROR;
-
- // Call the callback method
- result = PyObject_CallObject(callback, args);
- if (result && PyLong_Check(result)) {
- r = PyLong_AsLong(result);
- }
-
-ERROR:
- Py_XDECREF(args);
- Py_XDECREF(result);
-
- // Release the GIL
- PyGILState_Release(state);
-
- return r;
-}
-
-static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* kwds) {
- const char* kwlist[] = { "command", "environ", "bind", "callback", "nice", NULL };
-
- struct pakfire_jail* jail = NULL;
- const char** argv = NULL;
- int r;
- PyObject* ret = NULL;
-
- PyObject* command = NULL;
- PyObject* environ = NULL;
- PyObject* bind = NULL;
- PyObject* callback = NULL;
- int nice = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOi", (char**)kwlist, &command, &environ,
- &bind, &callback, &nice))
- return NULL;
-
- // Check if command is a list
- if (!PyList_Check(command)) {
- PyErr_SetString(PyExc_TypeError, "command must be a list");
- goto ERROR;
- }
-
- const ssize_t command_length = PyList_Size(command);
-
- // Check if command is not empty
- if (command_length == 0) {
- PyErr_SetString(PyExc_ValueError, "command is empty");
- goto ERROR;
- }
-
- // Allocate argv
- argv = calloc(command_length + 1, sizeof(*argv));
- if (!argv)
- goto ERROR;
-
- // All arguments in command must be strings
- for (unsigned int i = 0; i < command_length; i++) {
- PyObject* item = PyList_GET_ITEM(command, i);
-
- if (!PyUnicode_Check(item)) {
- PyErr_Format(PyExc_TypeError, "Item %u in command is not a string", i);
- goto ERROR;
- }
-
- // Copy to argv
- argv[i] = PyUnicode_AsUTF8(item);
- }
-
- // Check if bind is a sequence
- if (bind && !PySequence_Check(bind)) {
- PyErr_SetString(PyExc_ValueError, "bind is not a sequence");
- goto ERROR;
- }
-
- // Check callback
- if (callback && !PyCallable_Check(callback)) {
- PyErr_SetString(PyExc_TypeError, "callback must be callable\n");
- goto ERROR;
- }
-
- // Create jail
- r = pakfire_jail_create(&jail, self->pakfire);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto ERROR;
- }
-
- // Set nice
- if (nice) {
- r = pakfire_jail_nice(jail, nice);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto ERROR;
- }
- }
-
- PyObject* key = NULL;
- PyObject* value = NULL;
- Py_ssize_t p = 0;
-
- // Parse the environment
- if (environ) {
- // Check if environ is a dictionary
- if (!PyDict_Check(environ)) {
- PyErr_SetString(PyExc_TypeError, "environ must be a dictionary");
- goto ERROR;
- }
-
- // All keys and values must be strings
- while (PyDict_Next(environ, &p, &key, &value)) {
- if (!PyUnicode_Check(key) || !PyUnicode_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "Environment contains a non-string object");
- goto ERROR;
- }
-
- // Set environment value
- r = pakfire_jail_set_env(jail, PyUnicode_AsUTF8(key), PyUnicode_AsUTF8(value));
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto ERROR;
- }
- }
- }
-
- // Bind
- if (bind && PySequence_Check(bind)) {
- const Py_ssize_t num_bind = PySequence_Length(bind);
-
- for (unsigned int i = 0; i < num_bind; i++) {
- PyObject* b = PySequence_ITEM(bind, i);
- if (!b)
- goto ERROR;
-
- // Check if this is a Unicode object
- if (!PyUnicode_Check(b)) {
- PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
- Py_DECREF(b);
- goto ERROR;
- }
-
- const char* path = PyUnicode_AsUTF8(b);
-
- // Perform bind
- r = pakfire_jail_bind(jail, path, path, 0);
- if (r) {
- PyErr_SetFromErrno(PyExc_OSError);
- Py_DECREF(b);
- goto ERROR;
- }
-
- Py_DECREF(b);
- }
- }
-
- Py_BEGIN_ALLOW_THREADS
-
- // Set callback
- pakfire_jail_set_stdout_callback(jail, Pakfire_execute_output_callback, callback);
-
- // Execute command
- r = pakfire_jail_exec(jail, argv, 0, NULL);
-
- Py_END_ALLOW_THREADS
-
- // If the return code was negative, we had some internal error
- if (r < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto ERROR;
-
- // Otherwise the executed command returned some error code
- } else if (r > 0) {
- PyObject* code = PyLong_FromLong(r);
-
- // Raise CommandExecutionError
- PyErr_SetObject(PyExc_CommandExecutionError, code);
- Py_DECREF(code);
-
- goto ERROR;
- }
-
- // The process has exited successfully
-
- // Return None
- ret = Py_None;
- Py_INCREF(ret);
-
-ERROR:
- if (argv)
- free(argv);
- if (jail)
- pakfire_jail_unref(jail);
-
- return ret;
-}
-
static PyObject* Pakfire_dist(PakfireObject* self, PyObject* args) {
const char* path = NULL;
const char* target = NULL;
METH_VARARGS,
NULL
},
- {
- "execute",
- (PyCFunction)Pakfire_execute,
- METH_VARARGS|METH_KEYWORDS,
- NULL
- },
{
"generate_key",
(PyCFunction)Pakfire_generate_key,