* Execute
*/
+struct Pakfire_execute_input {
+ const char* data;
+ size_t length;
+};
+
+static ssize_t Pakfire_execute_stdin_callback(
+ struct pakfire_ctx* ctx, void* data, char* buffer, size_t length) {
+ struct Pakfire_execute_input* input = data;
+
+ // Return zero if we are done writing the input
+ if (!input->length)
+ return 0;
+
+ // Cap the memory if we have less input
+ if (input->length < length)
+ length = input->length;
+
+ // Copy the data into the output buffer
+ memcpy(buffer, input->data, length);
+
+ // Move the pointer forward
+ input->data += length;
+ input->length -= length;
+
+ return length;
+}
+
static int Pakfire_execute_stdout_callback(
struct pakfire_ctx* ctx, void* data, const char* line, const size_t length) {
PyObject** output = data;
}
static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject* kwargs) {
+ struct Pakfire_execute_input input = {};
struct pakfire_jail* jail = NULL;
struct pakfire_env* env = NULL;
const char** argv = NULL;
Py_ssize_t p = 0;
int r;
+ pakfire_pty_stdin_callback stdin_callback = NULL;
+
PyObject* command = NULL;
PyObject* environ = NULL;
int nice = 0;
PyObject* output = NULL;
int return_output = 0;
- pakfire_pty_stdout_callback stdout_callback = NULL;
-
const char* kwlist[] = {
"command",
"environ",
"nice",
"return_output",
+ "input",
NULL,
};
// Parse arguments
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oib", (char**)kwlist,
- &command, &environ, &nice, &return_output))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oiby#", (char**)kwlist,
+ &command, &environ, &nice, &return_output, &input.data, &input.length))
goto ERROR;
// Check if command is a list
if (!output)
goto ERROR;
+ // Register the input callback
+ if (input.data)
+ stdin_callback = Pakfire_execute_stdin_callback;
+
// Create a new jail
r = pakfire_jail_create(&jail, self->pakfire);
if (r < 0) {
// Execute command
r = pakfire_jail_communicate(jail, argv, env, 0,
- NULL, NULL, Pakfire_execute_stdout_callback, &output);
+ stdin_callback, &input, Pakfire_execute_stdout_callback, &output);
Py_END_ALLOW_THREADS
output = self.pakfire.execute(["/command", "lines", "100", "40"], return_output=True)
self.assertEquals(output.count(b"\n"), 100)
+ def test_execute_input(self):
+ def test(input, output=None):
+ #if output is None:
+ # output = input
+
+ # Pipe the data through the command
+ output = self.pakfire.execute(["/command", "pipe"],
+ input=input, return_output=True)
+
+ # Input and output must match
+ self.assertEqual(input, output)
+
+ # Test a simple, short string with a line ending
+ test(b"1234\n")
+
+ # Test a very long string
+ test(b"A" * 8192 + b"\n")
+
def test_nice(self):
self.pakfire.execute(["/command", "print-nice"], nice=5)