src/libpakfire/deps.c \
src/libpakfire/digest.c \
src/libpakfire/dist.c \
+ src/libpakfire/env.c \
src/libpakfire/fhs.c \
src/libpakfire/file.c \
src/libpakfire/filelist.c \
src/libpakfire/include/pakfire/deps.h \
src/libpakfire/include/pakfire/digest.h \
src/libpakfire/include/pakfire/dist.h \
+ src/libpakfire/include/pakfire/env.h \
src/libpakfire/include/pakfire/fhs.h \
src/libpakfire/include/pakfire/file.h \
src/libpakfire/include/pakfire/filelist.h \
goto ERROR;
// Run!
- r = pakfire_jail_communicate(jail, argv, PAKFIRE_JAIL_NOENT_OK,
+ r = pakfire_jail_communicate(jail, argv, NULL, PAKFIRE_JAIL_NOENT_OK,
pakfire_archive_stream_payload, a, NULL, NULL);
ERROR:
#include <pakfire/ctx.h>
#include <pakfire/deps.h>
#include <pakfire/dist.h>
+#include <pakfire/env.h>
#include <pakfire/file.h>
#include <pakfire/i18n.h>
#include <pakfire/jail.h>
// Jail
struct pakfire_jail* jail;
+ // Environment
+ struct pakfire_env* env;
+
// The build repository
struct pakfire_repo* repo;
}
// Execute the script
- r = pakfire_jail_exec_script(build->jail, script, length, args,
+ r = pakfire_jail_exec_script(build->jail, script, length, args, build->env,
stdin_callback, stdin_data, stdout_callback, stdout_data);
if (r)
ERROR(build->ctx, "Script '%s' failed with status %d\n", filename, r);
static int pakfire_build_stage(struct pakfire_build* build,
struct pakfire_parser* makefile, const char* stage) {
+ struct pakfire_env* env = NULL;
+ char* script = NULL;
char template[1024];
+ int r;
// Prepare template for this stage
- int r = pakfire_string_format(template, TEMPLATE, stage);
- if (r)
+ r = pakfire_string_format(template, TEMPLATE, stage);
+ if (r < 0)
return r;
// Fetch the environment
- char** envp = pakfire_parser_make_environ(makefile);
+ env = pakfire_parser_make_environ(makefile);
+ if (!env)
+ goto ERROR;
// Create the build script
- char* script = pakfire_parser_expand(makefile, "build", template);
+ script = pakfire_parser_expand(makefile, "build", template);
if (!script) {
ERROR(build->ctx, "Could not generate the build script for stage '%s': %m\n", stage);
goto ERROR;
INFO(build->ctx, "Running build stage '%s'\n", stage);
- // Import environment
- // XXX is this a good idea?
- r = pakfire_jail_import_env(build->jail, (const char**)envp);
- if (r) {
- ERROR(build->ctx, "Could not import environment: %m\n");
- goto ERROR;
- }
+ // XXX merge the basic environment
// Run the script
- r = pakfire_jail_exec_script(build->jail, script, strlen(script), NULL,
+ r = pakfire_jail_exec_script(build->jail, script, strlen(script), NULL, env,
NULL, NULL, pakfire_build_output_callback, build);
if (r)
ERROR(build->ctx, "Build stage '%s' failed with status %d\n", stage, r);
ERROR:
- if (envp) {
- for (char** e = envp; *e; e++)
- free(*e);
- free(envp);
- }
+ if (env)
+ pakfire_env_unref(env);
if (script)
free(script);
if (build->jail)
pakfire_jail_unref(build->jail);
+ if (build->env)
+ pakfire_env_unref(build->env);
if (build->cgroup) {
// Destroy the cgroup
DEBUG(build->ctx, "ccache usage has been disabled for this build\n");
// Set CCACHE_DISABLE=1 so that if ccache is installed, it will disable itself
- r = pakfire_jail_set_env(build->jail, "CCACHE_DISABLE", "1");
+ r = pakfire_env_set(build->env, "CCACHE_DISABLE", "1");
if (r) {
ERROR(build->ctx, "Could not disable ccache: %m\n");
return r;
}
// Set CCACHE_DIR
- r = pakfire_jail_set_env(build->jail, "CCACHE_DIR", CCACHE_DIR);
+ r = pakfire_env_set(build->env, "CCACHE_DIR", CCACHE_DIR);
if (r) {
ERROR(build->ctx, "Could not set ccache directory: %m\n");
return r;
}
// Set CCACHE_TEMPDIR
- r = pakfire_jail_set_env(build->jail, "CCACHE_TEMPDIR", "/tmp");
+ r = pakfire_env_set(build->env, "CCACHE_TEMPDIR", "/tmp");
if (r) {
ERROR(build->ctx, "Could not set ccache tempdir: %m\n");
return r;
// Copy flags
b->flags = flags;
+ // Create an environment
+ r = pakfire_env_create(&b->env, b->ctx);
+ if (r < 0)
+ goto ERROR;
+
// Store start time
r = pakfire_build_set_time_start(b);
if (r)
// Run the command (if given)
if (argv)
- return pakfire_jail_exec(build->jail, argv, 0);
+ return pakfire_jail_exec(build->jail, argv, build->env, 0);
// Otherwise run the shell
return pakfire_jail_shell(build->jail);
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2024 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <pakfire/ctx.h>
+#include <pakfire/env.h>
+#include <pakfire/string.h>
+
+#define ENVIRON_SIZE 128
+
+struct pakfire_env {
+ struct pakfire_ctx* ctx;
+ int nrefs;
+
+ char* env[ENVIRON_SIZE];
+};
+
+static void pakfire_env_free(struct pakfire_env* env) {
+ // Free environment
+ for (unsigned int i = 0; env->env[i]; i++)
+ free(env->env[i]);
+
+ if (env->ctx)
+ pakfire_ctx_unref(env->ctx);
+ free(env);
+}
+
+int pakfire_env_create(struct pakfire_env** env, struct pakfire_ctx* ctx) {
+ struct pakfire_env* e = NULL;
+
+ // Allocate a new environment
+ e = calloc(1, sizeof(*e));
+ if (!e)
+ return -errno;
+
+ // Store a reference to the context
+ e->ctx = pakfire_ctx_ref(ctx);
+
+ // Initialize the reference counter
+ e->nrefs = 1;
+
+ // Return the pointer
+ *env = e;
+
+ return 0;
+}
+
+struct pakfire_env* pakfire_env_ref(struct pakfire_env* env) {
+ ++env->nrefs;
+
+ return env;
+}
+
+struct pakfire_env* pakfire_env_unref(struct pakfire_env* env) {
+ if (--env->nrefs > 0)
+ return env;
+
+ pakfire_env_free(env);
+ return NULL;
+}
+
+char** pakfire_env_get_envp(struct pakfire_env* env) {
+ if (!env->env[0])
+ return NULL;
+
+ return env->env;
+}
+
+// Returns the length of the environment
+static unsigned int pakfire_env_length(struct pakfire_env* env) {
+ unsigned int i = 0;
+
+ // Count everything in the environment
+ for (char** e = env->env; *e; e++)
+ i++;
+
+ return i;
+}
+
+// Finds an existing environment variable and returns its index or -1 if not found
+static int pakfire_env_find(struct pakfire_env* env, const char* key) {
+ if (!key)
+ return -EINVAL;
+
+ const size_t length = strlen(key);
+
+ for (unsigned int i = 0; env->env[i]; i++) {
+ if ((pakfire_string_startswith(env->env[i], key)
+ && *(env->env[i] + length) == '=')) {
+ return i;
+ }
+ }
+
+ // Nothing found
+ return -1;
+}
+
+// Returns the value of an environment variable or NULL
+const char* pakfire_env_get(struct pakfire_env* env, const char* key) {
+ int i = pakfire_env_find(env, key);
+ if (i < 0)
+ return NULL;
+
+ return env->env[i] + strlen(key) + 1;
+}
+
+// Sets an environment variable
+int pakfire_env_set(struct pakfire_env* env, const char* key, const char* value) {
+ int r;
+
+ // Find the index where to write this value to
+ int i = pakfire_env_find(env, key);
+ if (i < 0)
+ i = pakfire_env_length(env);
+
+ // Return ENOBUFS when the environment is full
+ if (i >= ENVIRON_SIZE)
+ return -ENOBUFS;
+
+ // Free any previous value
+ if (env->env[i])
+ free(env->env[i]);
+
+ // Format and set environment variable
+ r = asprintf(&env->env[i], "%s=%s", key, value);
+ if (r < 0) {
+ ERROR(env->ctx, "Could not set environment variable %s: %m\n", key);
+ return -errno;
+ }
+
+ DEBUG(env->ctx, "Set environment variable: %s\n", env->env[i]);
+
+ return 0;
+}
+
+// Imports an environment
+int pakfire_env_import(struct pakfire_env* env, const char** e) {
+ char* key = NULL;
+ char* val = NULL;
+ int r;
+
+ // Is there anything to import?
+ if (!e)
+ return 0;
+
+ // Copy environment variables
+ for (unsigned int i = 0; e[i]; i++) {
+ r = pakfire_string_partition(e[i], "=", &key, &val);
+ if (r < 0)
+ continue;
+
+ // Set value
+ r = pakfire_env_set(env, key, val);
+
+ if (key)
+ free(key);
+ if (val)
+ free(val);
+
+ // Break on error
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+int pakfire_env_merge(struct pakfire_env* env1, struct pakfire_env* env2) {
+ return pakfire_env_import(env1, (const char**)env2->env);
+}
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2024 Pakfire development team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_ENV_H
+#define PAKFIRE_ENV_H
+
+#ifdef PAKFIRE_PRIVATE
+
+#include <pakfire/ctx.h>
+
+struct pakfire_env;
+
+int pakfire_env_create(struct pakfire_env** env, struct pakfire_ctx* ctx);
+
+struct pakfire_env* pakfire_env_ref(struct pakfire_env* env);
+struct pakfire_env* pakfire_env_unref(struct pakfire_env* env);
+
+char** pakfire_env_get_envp(struct pakfire_env* env);
+
+const char* pakfire_env_get(struct pakfire_env* env, const char* key);
+int pakfire_env_set(struct pakfire_env* env, const char* key, const char* value);
+
+int pakfire_env_import(struct pakfire_env* env, const char** e);
+
+int pakfire_env_merge(struct pakfire_env* env1, struct pakfire_env* env2);
+
+#endif /* PAKFIRE_PRIVATE */
+#endif /* PAKFIRE_ENV_H */
#ifdef PAKFIRE_PRIVATE
#include <pakfire/cgroup.h>
+#include <pakfire/env.h>
#include <pakfire/pakfire.h>
#include <pakfire/pty.h>
// Timeout
int pakfire_jail_set_timeout(struct pakfire_jail* jail, unsigned int timeout);
-// Environment
-const char* pakfire_jail_get_env(struct pakfire_jail* jail, const char* key);
-int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char* value);
-int pakfire_jail_import_env(struct pakfire_jail* jail, const char* env[]);
-
typedef int (*pakfire_jail_callback)(struct pakfire_jail* jail, void* data);
// Standard Input
PAKFIRE_JAIL_HAS_LOOP_DEVICES = (1 << 3),
};
-int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], int flags);
+int pakfire_jail_exec(struct pakfire_jail* jail,
+ const char* argv[], struct pakfire_env* env, int flags);
int pakfire_jail_exec_capture_output(struct pakfire_jail* jail,
- const char* argv[], int flags, char** output, size_t* length);
+ const char* argv[], struct pakfire_env* env, int flags, char** output, size_t* length);
// Resource limits
int pakfire_jail_set_cgroup(struct pakfire_jail* jail, struct pakfire_cgroup* cgroup);
int pakfire_jail_communicate(
- struct pakfire_jail* jail, const char* argv[], int flags,
+ struct pakfire_jail* jail, const char* argv[], struct pakfire_env* env, int flags,
pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
pakfire_pty_stdout_callback stdout_callback, void* stdout_data);
// Convenience functions
int pakfire_jail_run(struct pakfire* pakfire,
- const char* argv[], int flags, char** output, size_t* output_length);
+ const char* argv[], struct pakfire_env* env, int flags, char** output, size_t* output_length);
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[], struct pakfire_env* env, int flags);
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[], struct pakfire_env* env,
pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
pakfire_pty_stdout_callback stdout_callback, void* stdout_data);
struct pakfire_parser;
+#include <pakfire/env.h>
#include <pakfire/package.h>
#include <pakfire/parser.h>
#include <pakfire/repo.h>
int pakfire_parser_parse_data(struct pakfire_parser* parent, const char* data, size_t len,
struct pakfire_parser_error** error);
-char** pakfire_parser_make_environ(struct pakfire_parser* parser);
+struct pakfire_env* pakfire_parser_make_environ(struct pakfire_parser* parser);
#endif /* PAKFIRE_PRIVATE */
#include <pakfire/arch.h>
#include <pakfire/cgroup.h>
+#include <pakfire/env.h>
#include <pakfire/jail.h>
#include <pakfire/log_stream.h>
#include <pakfire/logging.h>
#include <pakfire/util.h>
#define BUFFER_SIZE 1024 * 64
-#define ENVIRON_SIZE 128
#define MAX_MOUNTPOINTS 8
// The default environment that will be set for every command
struct pakfire_cgroup* cgroup;
// Environment
- char* env[ENVIRON_SIZE];
+ struct pakfire_env* env;
// Mountpoints
struct pakfire_jail_mountpoint mountpoints[MAX_MOUNTPOINTS];
static void pakfire_jail_free(struct pakfire_jail* jail) {
DEBUG(jail->ctx, "Freeing jail at %p\n", jail);
- // Free environment
- for (unsigned int i = 0; jail->env[i]; i++)
- free(jail->env[i]);
-
if (jail->cgroup)
pakfire_cgroup_unref(jail->cgroup);
if (jail->pakfire)
pakfire_unref(jail->pakfire);
+ if (jail->env)
+ pakfire_env_unref(jail->env);
if (jail->ctx)
pakfire_ctx_unref(jail->ctx);
free(jail);
DEBUG(j->ctx, "Allocated new jail at %p\n", j);
+ // Create environment
+ r = pakfire_env_create(&j->env, j->ctx);
+ if (r < 0)
+ goto ERROR;
+
// Set default environment
for (const struct environ* e = ENV; e->key; e++) {
- r = pakfire_jail_set_env(j, e->key, e->val);
- if (r)
+ r = pakfire_env_set(j->env, e->key, e->val);
+ if (r < 0)
goto ERROR;
}
// Enable all CPU features that CPU has to offer
if (!pakfire_arch_is_supported_by_host(arch)) {
- r = pakfire_jail_set_env(j, "QEMU_CPU", "max");
- if (r)
+ r = pakfire_env_set(j->env, "QEMU_CPU", "max");
+ if (r < 0)
goto ERROR;
}
// Set container UUID
- r = pakfire_jail_set_env(j, "container_uuid", pakfire_jail_uuid(j));
- if (r)
+ r = pakfire_env_set(j->env, "container_uuid", pakfire_jail_uuid(j));
+ if (r < 0)
goto ERROR;
// Disable systemctl to talk to systemd
if (!pakfire_on_root(j->pakfire)) {
- r = pakfire_jail_set_env(j, "SYSTEMD_OFFLINE", "1");
- if (r)
+ r = pakfire_env_set(j->env, "SYSTEMD_OFFLINE", "1");
+ if (r < 0)
goto ERROR;
}
return 0;
}
-// Environment
-
-// Returns the length of the environment
-static unsigned int pakfire_jail_env_length(struct pakfire_jail* jail) {
- unsigned int i = 0;
-
- // Count everything in the environment
- for (char** e = jail->env; *e; e++)
- i++;
-
- return i;
-}
-
-// Finds an existing environment variable and returns its index or -1 if not found
-static int pakfire_jail_find_env(struct pakfire_jail* jail, const char* key) {
- if (!key) {
- errno = EINVAL;
- return -1;
- }
-
- const size_t length = strlen(key);
-
- for (unsigned int i = 0; jail->env[i]; i++) {
- if ((pakfire_string_startswith(jail->env[i], key)
- && *(jail->env[i] + length) == '=')) {
- return i;
- }
- }
-
- // Nothing found
- return -1;
-}
-
-// Returns the value of an environment variable or NULL
-const char* pakfire_jail_get_env(struct pakfire_jail* jail,
- const char* key) {
- int i = pakfire_jail_find_env(jail, key);
- if (i < 0)
- return NULL;
-
- return jail->env[i] + strlen(key) + 1;
-}
-
-// Sets an environment variable
-int pakfire_jail_set_env(struct pakfire_jail* jail,
- const char* key, const char* value) {
- // Find the index where to write this value to
- int i = pakfire_jail_find_env(jail, key);
- if (i < 0)
- i = pakfire_jail_env_length(jail);
-
- // Return -ENOSPC when the environment is full
- if (i >= ENVIRON_SIZE) {
- errno = ENOSPC;
- return -1;
- }
-
- // Free any previous value
- if (jail->env[i])
- free(jail->env[i]);
-
- // Format and set environment variable
- asprintf(&jail->env[i], "%s=%s", key, value);
-
- DEBUG(jail->ctx, "Set environment variable: %s\n", jail->env[i]);
-
- return 0;
-}
-
-// Imports an environment
-int pakfire_jail_import_env(struct pakfire_jail* jail, const char* env[]) {
- if (!env)
- return 0;
-
- char* key;
- char* val;
- int r;
-
- // Copy environment variables
- for (unsigned int i = 0; env[i]; i++) {
- r = pakfire_string_partition(env[i], "=", &key, &val);
- if (r)
- continue;
-
- // Set value
- r = pakfire_jail_set_env(jail, key, val);
-
- if (key)
- free(key);
- if (val)
- free(val);
-
- // Break on error
- if (r)
- return r;
- }
-
- return 0;
-}
-
// Timeout
int pakfire_jail_set_timeout(
struct pakfire_jail_command {
const char** argv;
- const char** envp;
+ struct pakfire_env* env;
};
static int pakfire_jail_launch_command(struct pakfire_jail* jail, void* data) {
struct pakfire_jail_command* command = data;
+ char** envp = NULL;
int r;
// Check if argv is valid
for (unsigned int i = 0; command->argv[i]; i++)
DEBUG(jail->ctx, " argv[%u] = %s\n", i, command->argv[i]);
+ // Fetch the environment
+ if (command->env) {
+ envp = pakfire_env_get_envp(command->env);
+ if (!envp)
+ return -ENOTSUP;
+ }
+
// exec() command
- r = execvpe(command->argv[0], (char**)command->argv, (char**)command->envp);
+ r = execvpe(command->argv[0], (char**)command->argv, envp);
if (r < 0) {
// Translate errno into regular exit code
switch (errno) {
return r;
}
-int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], int flags) {
+int pakfire_jail_exec(struct pakfire_jail* jail,
+ const char* argv[], struct pakfire_env* env, int flags) {
struct pakfire_jail_command command = {
.argv = argv,
+ .env = env,
};
return __pakfire_jail_exec(jail, pakfire_jail_launch_command, &command, flags,
}
int pakfire_jail_exec_capture_output(struct pakfire_jail* jail,
- const char* argv[], int flags, char** output, size_t* length) {
+ const char* argv[], struct pakfire_env* env, int flags, char** output, size_t* length) {
struct pakfire_jail_command command = {
.argv = argv,
+ .env = env,
};
return __pakfire_jail_exec(jail, pakfire_jail_launch_command, &command, flags,
}
int pakfire_jail_communicate(
- struct pakfire_jail* jail, const char* argv[], int flags,
+ struct pakfire_jail* jail, const char* argv[], struct pakfire_env* env, int flags,
pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
pakfire_pty_stdout_callback stdout_callback, void* stdout_data) {
struct pakfire_jail_command command = {
.argv = argv,
+ .env = env,
};
return __pakfire_jail_exec(jail, pakfire_jail_launch_command, &command, flags,
}
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[], struct pakfire_env* env,
pakfire_pty_stdin_callback stdin_callback, void* stdin_data,
pakfire_pty_stdout_callback stdout_callback, void* stdout_data) {
char path[PATH_MAX];
argv[i] = args[i-1];
// Run the script
- r = pakfire_jail_communicate(jail, argv, 0,
+ r = pakfire_jail_communicate(jail, argv, env, 0,
stdin_callback, stdin_data, stdout_callback, stdout_data);
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, char** output, size_t* output_length) {
+int pakfire_jail_run(struct pakfire* pakfire, const char* argv[], struct pakfire_env* env,
+ int flags, char** output, size_t* output_length) {
struct pakfire_jail* jail = NULL;
int r;
goto ERROR;
// Execute the command
- r = pakfire_jail_exec_capture_output(jail, argv, flags, output, output_length);
+ r = pakfire_jail_exec_capture_output(jail, argv, env, flags, output, output_length);
ERROR:
if (jail)
return r;
}
-int pakfire_jail_run_script(struct pakfire* pakfire,
- const char* script, const size_t length, const char* argv[], int flags) {
+int pakfire_jail_run_script(struct pakfire* pakfire, const char* script, const size_t length,
+ const char* argv[], struct pakfire_env* env, int flags) {
struct pakfire_jail* jail = NULL;
int r;
goto ERROR;
// Execute the command
- r = pakfire_jail_exec_script(jail, script, length, argv, NULL, NULL, NULL, NULL);
+ r = pakfire_jail_exec_script(jail, script, length, argv, env, NULL, NULL, NULL, NULL);
ERROR:
if (jail)
}
int pakfire_jail_shell(struct pakfire_jail* jail) {
+ struct pakfire_env* env = NULL;
int r;
const char* argv[] = {
"/bin/bash", "--login", NULL,
};
+ // Create a new environment
+ r = pakfire_env_create(&env, jail->ctx);
+ if (r < 0)
+ goto ERROR;
+
// Copy TERM
char* TERM = secure_getenv("TERM");
if (TERM) {
- r = pakfire_jail_set_env(jail, "TERM", TERM);
- if (r)
- return r;
+ r = pakfire_env_set(env, "TERM", TERM);
+ if (r < 0)
+ goto ERROR;
}
// Copy LANG
char* LANG = secure_getenv("LANG");
if (LANG) {
- r = pakfire_jail_set_env(jail, "LANG", LANG);
- if (r)
- return r;
+ r = pakfire_env_set(env, "LANG", LANG);
+ if (r < 0)
+ goto ERROR;
}
// Execute /bin/bash
- r = pakfire_jail_exec(jail, argv, PAKFIRE_JAIL_INTERACTIVE);
-
- // Raise any errors
+ r = pakfire_jail_exec(jail, argv, env, PAKFIRE_JAIL_INTERACTIVE);
if (r < 0)
- return r;
+ goto ERROR;
// Ignore any return codes from the shell
- return 0;
+ r = 0;
+
+ERROR:
+ if (env)
+ pakfire_env_unref(env);
+
+ return r;
}
static int pakfire_jail_run_if_possible(struct pakfire* pakfire, const char** argv) {
goto ERROR;
}
- r = pakfire_jail_run(pakfire, argv, 0, NULL, NULL);
+ r = pakfire_jail_run(pakfire, argv, NULL, 0, NULL, NULL);
ERROR:
if (ctx)
#include <pakfire/ctx.h>
#include <pakfire/deps.h>
+#include <pakfire/env.h>
#include <pakfire/jail.h>
#include <pakfire/logging.h>
#include <pakfire/package.h>
size_t length = 0;
// Execute the command inside the Pakfire environment
- r = pakfire_jail_run(parser->pakfire, argv, 0, &output, &length);
+ r = pakfire_jail_run(parser->pakfire, argv, NULL, 0, &output, &length);
if (r) {
// Just log this and continue
DEBUG(parser->ctx, "Command '%s' failed with return code %d\n", command, r);
return 0;
}
-char** pakfire_parser_make_environ(struct pakfire_parser* parser) {
- char** envp = NULL;
- unsigned int num = 0;
+struct pakfire_env* pakfire_parser_make_environ(struct pakfire_parser* parser) {
+ struct pakfire_parser_declaration* d = NULL;
+ struct pakfire_env* env = NULL;
+ char* value = NULL;
+ int r;
+
+ // Create a new empty environment
+ r = pakfire_env_create(&env, parser->ctx);
+ if (r < 0)
+ goto ERROR;
for (unsigned int i = 0; i < parser->num_declarations; i++) {
- struct pakfire_parser_declaration* d = parser->declarations[i];
+ d = parser->declarations[i];
if (!d)
continue;
// Is the export flag set?
if (d->flags & PAKFIRE_PARSER_DECLARATION_EXPORT) {
- char* buffer = NULL;
-
- char* value = pakfire_parser_expand(parser, d->namespace, d->value);
+ value = pakfire_parser_expand(parser, d->namespace, d->value);
if (!value)
goto ERROR;
- // Build line
- int r = asprintf(&buffer, "%s=%s", d->name, value);
- free(value);
+ // Store the value
+ r = pakfire_env_set(env, d->name, value);
if (r < 0)
goto ERROR;
-
- // Extend the array
- envp = reallocarray(envp, num + 2, sizeof(*envp));
- if (!envp)
- goto ERROR;
-
- envp[num++] = buffer;
- envp[num] = NULL;
}
}
- return envp;
+ return env;
ERROR:
- if (envp) {
- for (char** e = envp; *e; e++)
- free(*e);
- free(envp);
- }
+ if (env)
+ pakfire_env_unref(env);
return NULL;
}
int pakfire_scriptlet_execute(struct pakfire_scriptlet* scriptlet, struct pakfire* pakfire) {
// Detect what kind of script this is and run it
if (pakfire_scriptlet_is_shell_script(scriptlet))
- return pakfire_jail_run_script(pakfire, scriptlet->data, scriptlet->size, NULL, 0);
+ return pakfire_jail_run_script(pakfire, scriptlet->data, scriptlet->size, NULL, NULL, 0);
ERROR(scriptlet->ctx, "Scriptlet is of an unknown kind\n");
return -ENOTSUP;
// Run a few things
for (unsigned int i = 0; i < 3; i++) {
- ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, 0));
+ ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, NULL, 0));
}
// Try reading the stats into some invalid space
ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
// Check if we receive the correct exit code
- ASSERT(pakfire_jail_exec(jail, argv, 0) == 123);
+ ASSERT(pakfire_jail_exec(jail, argv, NULL, 0) == 123);
// Success
r = EXIT_SUCCESS;
ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
// Check if we receive the correct exit code
- ASSERT(pakfire_jail_exec(jail, argv, 0) == 139);
+ ASSERT(pakfire_jail_exec(jail, argv, NULL, 0) == 139);
// Success
r = EXIT_SUCCESS;
return r;
}
-static int test_env(const struct test* t) {
- struct pakfire_jail* jail = NULL;
-
- // Create a new jail
- ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
-
- // Check if the default variables are set
- ASSERT(pakfire_jail_get_env(jail, "LANG"));
- ASSERT(pakfire_jail_get_env(jail, "TERM"));
-
- // Fetch a non-existing environment variable
- ASSERT_NULL(pakfire_jail_get_env(jail, "VARIABLE"));
-
- // Set a variable
- ASSERT_SUCCESS(pakfire_jail_set_env(jail, "VARIABLE", "VALUE"));
-
- // Read the value back
- ASSERT_STRING_EQUALS(pakfire_jail_get_env(jail, "VARIABLE"), "VALUE");
-
- // Destroy it
- ASSERT_NULL(pakfire_jail_unref(jail));
-
- return EXIT_SUCCESS;
-
-FAIL:
- return EXIT_FAILURE;
-}
-
static int test_exec(const struct test* t) {
struct pakfire_jail* jail = NULL;
char* output = NULL;
ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
// Try to execute something
- ASSERT_SUCCESS(pakfire_jail_exec_capture_output(jail, cmd_hello_world, 0, &output, &length));
+ ASSERT_SUCCESS(pakfire_jail_exec_capture_output(jail, cmd_hello_world, NULL, 0, &output, &length));
// We should have some output
ASSERT_STRING_EQUALS(output, "Hello World!\n");
ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
// Run command
- ASSERT(pakfire_jail_exec(jail, cmd_hello_world, 0) == 0);
+ ASSERT(pakfire_jail_exec(jail, cmd_hello_world, NULL, 0) == 0);
r = EXIT_SUCCESS;
ASSERT_SUCCESS(pakfire_jail_nice(jail, 5));
// Check if the nice level has been set
- ASSERT_SUCCESS(pakfire_jail_exec_capture_output(jail, argv, 0, &output, NULL));
+ ASSERT_SUCCESS(pakfire_jail_exec_capture_output(jail, argv, NULL, 0, &output, NULL));
ASSERT_STRING_EQUALS(output, "5\n");
// Success
ASSERT_SUCCESS(pakfire_cgroup_set_memory_limit(cgroup, 100 * 1024 * 1024));
// Try to exhaust all memory
- ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_exhaust_memory, 0));
+ ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_exhaust_memory, NULL, 0));
// A fork bomb should also exhaust all memory
- ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, 0));
+ ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL, 0));
// Success
r = EXIT_SUCCESS;
ASSERT_SUCCESS(pakfire_cgroup_set_pid_limit(cgroup, 100));
// Try to fork as many processes as possible
- ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, 0));
+ ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL, 0));
// Success
r = EXIT_SUCCESS;
char* output = NULL;
// Execute a simple command
- ASSERT_SUCCESS(pakfire_jail_run(t->pakfire, cmd_stat_ownership, 0, &output, NULL));
+ ASSERT_SUCCESS(pakfire_jail_run(t->pakfire, cmd_stat_ownership, NULL, 0, &output, NULL));
// Check if the file has been mapped to root/root
ASSERT_STRING_EQUALS(output, "uid=0 gid=0\n");
ASSERT_SUCCESS(pakfire_jail_bind(jail, source, target, MS_RDONLY));
// Check if the mount actually works
- ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, 0));
+ ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, NULL, 0));
// Success
r = EXIT_SUCCESS;
ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire));
// Check if the mount actually works
- ASSERT_SUCCESS(pakfire_jail_communicate(jail, argv, 0,
+ ASSERT_SUCCESS(pakfire_jail_communicate(jail, argv, NULL, 0,
callback_stdin, &lines, NULL, NULL));
// Success
};
// Perform the command
- return pakfire_jail_exec(jail, argv, 0);
+ return pakfire_jail_exec(jail, argv, NULL, 0);
}
static int test_send_signal(const struct test* t) {
ASSERT_SUCCESS(pakfire_jail_set_timeout(jail, 1));
// Check if we receive the correct exit code
- ASSERT(pakfire_jail_exec(jail, argv, 0) == 139);
+ ASSERT(pakfire_jail_exec(jail, argv, NULL, 0) == 139);
// Success
r = EXIT_SUCCESS;
testsuite_add_test(test_create, TEST_WANTS_PAKFIRE);
testsuite_add_test(test_exit_code, TEST_WANTS_PAKFIRE);
testsuite_add_test(test_segv, TEST_WANTS_PAKFIRE);
- testsuite_add_test(test_env, TEST_WANTS_PAKFIRE);
testsuite_add_test(test_exec, TEST_WANTS_PAKFIRE);
#if 0
testsuite_add_test(test_launch_into_cgroup, TEST_WANTS_PAKFIRE);