]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
jail: Add option to collect stdout
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 3 Aug 2022 10:17:37 +0000 (10:17 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 3 Aug 2022 10:17:37 +0000 (10:17 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/execute.c
src/libpakfire/include/pakfire/execute.h
src/libpakfire/include/pakfire/jail.h
src/libpakfire/jail.c
src/libpakfire/parser.c
src/libpakfire/scriptlet.c
tests/libpakfire/jail.c

index 91f11cd11272838ebaceafcea7c4c5b82540035e..769dbdee932e3ec829e1b8a921efd36ec4403e6a 100644 (file)
@@ -26,7 +26,6 @@
 #include <uuid/uuid.h>
 
 #include <pakfire/build.h>
-#include <pakfire/execute.h>
 #include <pakfire/dist.h>
 #include <pakfire/file.h>
 #include <pakfire/jail.h>
@@ -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;
        }
index 1619248f0180e5569fb5f5c7a4728eaeae2e4611..20aef735cce1f457244e24dfe4f81de643fb2a3e 100644 (file)
 
 #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);
 }
index 58d585251226ec4d917d3713062002d1b4884f31..660c22e15987577415a4cf6bf6fc1cbfffe3d16e 100644 (file)
@@ -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);
 
index 6901d7b98057ca4da2064ec6c88d9965dc17149f..bda8d91d8951f8dc48d6fcdc3ee3888421d8608d 100644 (file)
@@ -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
 
index 57de2b6e24fd0546012b317c5ce43b23c9809102..39362d477724ce2d76df37e46f0a15a9bbeda730 100644 (file)
@@ -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)
index 54fb50aa247660d6f34fac4efde13cfbe8816768..16c3f34e14fb183ff5f10e6993d322635913e492 100644 (file)
@@ -30,7 +30,7 @@
 #define PCRE2_CODE_UNIT_WIDTH 8
 #include <pcre2.h>
 
-#include <pakfire/execute.h>
+#include <pakfire/jail.h>
 #include <pakfire/logging.h>
 #include <pakfire/package.h>
 #include <pakfire/parser.h>
@@ -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);
        }
index 099af7a29c172d8c99f862b74bf3b00e7ff03ed3..8b41646f6391378725ac0e8eda8eb79f86e7fc10 100644 (file)
@@ -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;
index ec7a6b65baf44ee1cfc536fe400f1a223b20d24f..757cd9e890453195639b855047e8de1fefb178b8 100644 (file)
@@ -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));