From: Michael Tremer Date: Wed, 3 Aug 2022 10:17:37 +0000 (+0000) Subject: jail: Add option to collect stdout X-Git-Tag: 0.9.28~601 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0de6bb3036f80b313ed9781750f48b2a2c502491;p=pakfire.git jail: Add option to collect stdout Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 91f11cd11..769dbdee9 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -82,8 +81,8 @@ ERROR: return NULL; } -static int pakfire_build_run_script(struct pakfire* pakfire, const char* filename, const char* args[], - pakfire_execute_logging_callback logging_callback, void* data) { +static int pakfire_build_run_script(struct pakfire* pakfire, const char* filename, + const char* args[], char*** output) { struct pakfire_jail* jail = NULL; char* script = NULL; size_t size = 0; @@ -113,15 +112,8 @@ static int pakfire_build_run_script(struct pakfire* pakfire, const char* filenam if (!jail) goto ERROR; - // Configure logging - if (logging_callback) { - r = pakfire_jail_set_log_callback(jail, logging_callback, data); - if (r) - goto ERROR; - } - // Execute the script - r = pakfire_jail_exec_script(jail, script, size, args); + r = pakfire_jail_exec_script(jail, script, size, args, output); if (r) { ERROR(pakfire, "Script '%s' failed with status %d\n", filename, r); } @@ -184,16 +176,14 @@ static int pakfire_build_find_dependencies(struct pakfire* pakfire, }; // Find all provides - r = pakfire_build_run_script(pakfire, "find-provides", args, - pakfire_execute_capture_stdout_to_array, &provides); + r = pakfire_build_run_script(pakfire, "find-provides", args, &provides); if (r) { ERROR(pakfire, "find-provides returned with error %d\n", r); goto ERROR; } // Find all requires - r = pakfire_build_run_script(pakfire, "find-requires", args, - pakfire_execute_capture_stdout_to_array, &requires); + r = pakfire_build_run_script(pakfire, "find-requires", args, &requires); if (r) { ERROR(pakfire, "find-requires returned with error %d\n", r); goto ERROR; @@ -395,8 +385,7 @@ static int pakfire_build_add_scriptlet_requires(struct pakfire* pakfire, struct }; // Find all pre-requires - r = pakfire_build_run_script(pakfire, "find-prerequires", args, - pakfire_execute_capture_stdout_to_array, &prerequires); + r = pakfire_build_run_script(pakfire, "find-prerequires", args, &prerequires); if (r) goto ERROR; @@ -654,7 +643,7 @@ static int pakfire_build_stage(struct pakfire* pakfire, struct pakfire_parser* m } // Run the script - r = pakfire_jail_exec_script(jail, script, strlen(script), NULL); + r = pakfire_jail_exec_script(jail, script, strlen(script), NULL, NULL); if (r) { ERROR(pakfire, "Build stage '%s' failed with status %d\n", stage, r); } @@ -697,7 +686,7 @@ static int pakfire_build_run_post_build_scripts(struct pakfire* pakfire, const c // Run them one by one for (const char** script = post_build_scripts; *script; script++) { - int r = pakfire_build_run_script(pakfire, *script, args, NULL, NULL); + int r = pakfire_build_run_script(pakfire, *script, args, NULL); if (r) return r; } diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index 1619248f0..20aef735c 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -31,74 +31,6 @@ #define LDCONFIG "/sbin/ldconfig" -static int default_logging_callback(struct pakfire* pakfire, void* data, int priority, - const char* line, size_t length) { - switch (priority) { - case LOG_INFO: - INFO(pakfire, "%s", line); - break; - - case LOG_ERR: - ERROR(pakfire, "%s", line); - break; - } - - return 0; -} - -int pakfire_execute_capture_stdout(struct pakfire* pakfire, void* data, int priority, - const char* line, size_t length) { - char** output = (char**)data; - - // Append everything from stdout to a buffer - if (priority == LOG_INFO) { - int r = asprintf(output, "%s%s", (output && *output) ? *output : "", line); - if (r) - return 1; - } - - // Send everything else to the default logger - return default_logging_callback(pakfire, NULL, priority, line, length); -} - -int pakfire_execute_capture_stdout_to_array(struct pakfire* pakfire, void* data, int priority, - const char* line, size_t length) { - char*** array = (char***)data; - - // Append everything from stdout to an array - if (priority == LOG_INFO) { - length = 0; - - // Create a copy of line - char* message = strdup(line); - if (!message) - return 1; - - // Remove any trailing newline - pakfire_remove_trailing_newline(message); - - // Determine the length of the existing array - if (*array) { - for (char** element = *array; *element; element++) - length++; - } - - // Allocate space - *array = reallocarray(*array, length + 2, sizeof(**array)); - if (!*array) - return 1; - - // Append message and terminate the array - (*array)[length] = message; - (*array)[length + 1] = NULL; - - return 0; - } - - // Send everything else to the default logger - return default_logging_callback(pakfire, NULL, priority, line, length); -} - PAKFIRE_EXPORT int pakfire_execute(struct pakfire* pakfire, const char* argv[], char* envp[], int flags, pakfire_execute_logging_callback logging_callback, void* data) { struct pakfire_jail* jail = NULL; @@ -122,7 +54,7 @@ PAKFIRE_EXPORT int pakfire_execute(struct pakfire* pakfire, const char* argv[], goto ERROR; // Execute the command - r = pakfire_jail_exec(jail, argv); + r = pakfire_jail_exec(jail, argv, NULL); ERROR: if (jail) @@ -137,7 +69,7 @@ int pakfire_execute_shell(struct pakfire* pakfire) { }; // Execute /bin/bash - return pakfire_jail_run(pakfire, argv, PAKFIRE_JAIL_INTERACTIVE); + return pakfire_jail_run(pakfire, argv, PAKFIRE_JAIL_INTERACTIVE, NULL); } int pakfire_execute_ldconfig(struct pakfire* pakfire) { @@ -160,5 +92,5 @@ int pakfire_execute_ldconfig(struct pakfire* pakfire) { }; // Run ldconfig - return pakfire_jail_run(pakfire, argv, 0); + return pakfire_jail_run(pakfire, argv, 0, NULL); } diff --git a/src/libpakfire/include/pakfire/execute.h b/src/libpakfire/include/pakfire/execute.h index 58d585251..660c22e15 100644 --- a/src/libpakfire/include/pakfire/execute.h +++ b/src/libpakfire/include/pakfire/execute.h @@ -37,10 +37,6 @@ enum { #ifdef PAKFIRE_PRIVATE -int pakfire_execute_capture_stdout(struct pakfire* pakfire, void* data, int priority, - const char* line, size_t length); -int pakfire_execute_capture_stdout_to_array(struct pakfire* pakfire, void* data, int priority, - const char* line, size_t length); int pakfire_execute_shell(struct pakfire* pakfire); int pakfire_execute_ldconfig(struct pakfire* pakfire); diff --git a/src/libpakfire/include/pakfire/jail.h b/src/libpakfire/include/pakfire/jail.h index 6901d7b98..bda8d91d8 100644 --- a/src/libpakfire/include/pakfire/jail.h +++ b/src/libpakfire/include/pakfire/jail.h @@ -50,14 +50,14 @@ int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char* int pakfire_jail_import_env(struct pakfire_jail* jail, const char* env[]); // Execute -int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]); +int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], char*** output); int pakfire_jail_exec_script(struct pakfire_jail* jail, - const char* script, const size_t size, const char* args[]); + const char* script, const size_t size, const char* args[], char*** output); // Convenience functions -int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags); +int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags, char*** output); int pakfire_jail_run_script(struct pakfire* pakfire, - const char* script, const size_t length, const char* argv[], int flags); + const char* script, const size_t length, const char* argv[], int flags, char*** output); #endif diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index 57de2b6e2..39362d477 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -495,6 +495,44 @@ OUT: return r; } +static int pakfire_jail_capture_stdout(struct pakfire* pakfire, void* data, int priority, + const char* line, size_t length) { + char*** array = (char***)data; + + // Append everything from stdout to an array + if (priority == LOG_INFO) { + length = 0; + + // Create a copy of line + char* message = strdup(line); + if (!message) + return 1; + + // Remove any trailing newline + pakfire_remove_trailing_newline(message); + + // Determine the length of the existing array + if (*array) { + for (char** element = *array; *element; element++) + length++; + } + + // Allocate space + *array = reallocarray(*array, length + 2, sizeof(**array)); + if (!*array) + return 1; + + // Append message and terminate the array + (*array)[length] = message; + (*array)[length + 1] = NULL; + + return 0; + } + + // Send everything else to the default logger + return pakfire_jail_default_log_callback(pakfire, NULL, priority, line, length); +} + // Capabilities static int pakfire_jail_drop_capabilities(struct pakfire_jail* jail) { @@ -972,7 +1010,7 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe } // Run a command in the jail -int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) { +static int __pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) { int exit = -1; int r; @@ -1090,8 +1128,28 @@ ERROR: return exit; } +int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], char*** output) { + int r; + + // Store logging callback + pakfire_jail_log_callback log_callback = jail->log_callback; + void* log_data = jail->log_data; + + // Capture output if requested by user + if (output) + pakfire_jail_set_log_callback(jail, pakfire_jail_capture_stdout, output); + + // Run exec() + r = __pakfire_jail_exec(jail, argv); + + // Restore log callback + pakfire_jail_set_log_callback(jail, log_callback, log_data); + + return r; +} + int pakfire_jail_exec_script(struct pakfire_jail* jail, - const char* script, const size_t size, const char* args[]) { + const char* script, const size_t size, const char* args[], char*** output) { char path[PATH_MAX]; const char** argv = NULL; int r; @@ -1157,7 +1215,7 @@ int pakfire_jail_exec_script(struct pakfire_jail* jail, argv[i] = args[i-1]; // Run the script - r = pakfire_jail_exec(jail, argv); + r = pakfire_jail_exec(jail, argv, output); ERROR: if (argv) @@ -1174,7 +1232,7 @@ ERROR: A convenience function that creates a new jail, runs the given command and destroys the jail again. */ -int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags) { +int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags, char*** output) { struct pakfire_jail* jail = NULL; int r; @@ -1184,7 +1242,7 @@ int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], int flags) { goto ERROR; // Execute the command - r = pakfire_jail_exec(jail, argv); + r = pakfire_jail_exec(jail, argv, output); ERROR: if (jail) @@ -1194,7 +1252,7 @@ ERROR: } int pakfire_jail_run_script(struct pakfire* pakfire, - const char* script, const size_t length, const char* argv[], int flags) { + const char* script, const size_t length, const char* argv[], int flags, char*** output) { struct pakfire_jail* jail = NULL; int r; @@ -1204,7 +1262,7 @@ int pakfire_jail_run_script(struct pakfire* pakfire, goto ERROR; // Execute the command - r = pakfire_jail_exec_script(jail, script, length, argv); + r = pakfire_jail_exec_script(jail, script, length, argv, output); ERROR: if (jail) diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 54fb50aa2..16c3f34e1 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -30,7 +30,7 @@ #define PCRE2_CODE_UNIT_WIDTH 8 #include -#include +#include #include #include #include @@ -449,16 +449,18 @@ static int pakfire_parser_expand_commands(struct pakfire_parser* parser, char** argv[2] = (const char*)command; // The output of the command - char* output = NULL; + char** stdout = NULL; // Execute the command inside the Pakfire environment - r = pakfire_execute(parser->pakfire, argv, NULL, 0, - pakfire_execute_capture_stdout, &output); + r = pakfire_jail_run(parser->pakfire, argv, 0, &stdout); if (r) { // Just log this and continue DEBUG(parser->pakfire, "Command '%s' failed with return code %d\n", command, r); } + // Join all output together + char* output = pakfire_string_join(stdout, ""); + // Strip newline from output if (output) pakfire_remove_trailing_newline(output); @@ -492,6 +494,12 @@ static int pakfire_parser_expand_commands(struct pakfire_parser* parser, char** pcre2_substring_free(pattern); pattern = NULL; + if (stdout) { + for (char** line = stdout; *line; line++) + free(*line); + free(stdout); + } + if (output) free(output); } diff --git a/src/libpakfire/scriptlet.c b/src/libpakfire/scriptlet.c index 099af7a29..8b41646f6 100644 --- a/src/libpakfire/scriptlet.c +++ b/src/libpakfire/scriptlet.c @@ -169,7 +169,7 @@ int pakfire_scriptlet_execute(struct pakfire_scriptlet* scriptlet) { // Detect what kind of script this is and run it if (pakfire_scriptlet_is_shell_script(scriptlet)) return pakfire_jail_run_script(scriptlet->pakfire, - scriptlet->data, scriptlet->size, NULL, 0); + scriptlet->data, scriptlet->size, NULL, 0, NULL); ERROR(scriptlet->pakfire, "Scriptlet is of an unknown kind\n"); errno = ENOTSUP; diff --git a/tests/libpakfire/jail.c b/tests/libpakfire/jail.c index ec7a6b65b..757cd9e89 100644 --- a/tests/libpakfire/jail.c +++ b/tests/libpakfire/jail.c @@ -87,7 +87,7 @@ static int test_exec(const struct test* t) { ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0)); // Try to execute something - ASSERT(pakfire_jail_exec(jail, argv) == 127); + ASSERT(pakfire_jail_exec(jail, argv, NULL) == 127); // Destroy it ASSERT_NULL(pakfire_jail_unref(jail));