From: Michael Tremer Date: Fri, 21 May 2021 09:51:53 +0000 (+0000) Subject: execute: Move setting default environment into libpakfire X-Git-Tag: 0.9.28~1285^2~111 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a51f0370d5190650147a391382bb109067339700;p=pakfire.git execute: Move setting default environment into libpakfire Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/execute.c b/src/libpakfire/execute.c index 13ccce8f4..a75da8e67 100644 --- a/src/libpakfire/execute.c +++ b/src/libpakfire/execute.c @@ -41,16 +41,25 @@ #include #include +#define ENVIRON_SIZE 128 #define BUFFER_SIZE 1024 * 64 #define EPOLL_MAX_EVENTS 2 #define LDCONFIG "/sbin/ldconfig" -static char* envp_empty[1] = { NULL }; +// The default environment that will be set for every command +static const struct environ { + const char* key; + const char* val; +} default_environ[] = { + { "LANG", "en_US.utf-8" }, + { "TERM", "vt100" }, + { NULL, NULL }, +}; struct pakfire_execute { Pakfire pakfire; const char** argv; - char** envp; + char* envp[ENVIRON_SIZE]; char cgroup[PATH_MAX]; @@ -250,6 +259,50 @@ static int default_logging_callback(Pakfire pakfire, void* data, int priority, return 0; } +static int find_environ(struct pakfire_execute* env, const char* key) { + if (!key) { + errno = EINVAL; + return -1; + } + + char buffer[strlen(key) + 2]; + unsigned int i = 0; + + pakfire_string_format(buffer, "%s=", key); + + for (i = 0; env->envp[i]; i++) { + if (pakfire_string_startswith(env->envp[i], buffer)) + return i; + } + + // Return -ENOSPC when the environment is full + if (i >= ENVIRON_SIZE) { + errno = ENOSPC; + return -1; + } + + // Return the index of the next free slot + return i; +} + +static int set_environ(struct pakfire_execute* env, const char* key, const char* value) { + // Find the index where to write this value to + int idx = find_environ(env, key); + if (idx < 0) + return idx; + + // Free any previous value + if (env->envp[idx]) + free(env->envp[idx]); + + // Format and set environment variable + asprintf(&env->envp[idx], "%s=%s", key, value); + + DEBUG(env->pakfire, "Set environment variable: %s\n", env->envp[idx]); + + return 0; +} + static int pakfire_execute_fork(void* data) { struct pakfire_execute* env = (struct pakfire_execute*)data; @@ -338,11 +391,11 @@ static int pakfire_execute_fork(void* data) { PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* envp[], int flags, pakfire_execute_logging_callback logging_callback, void* data) { DIR* cgroupdir = NULL; + int r; struct pakfire_execute env = { .pakfire = pakfire, .argv = argv, - .envp = envp, .cgroup = "pakfire/execute-XXXXXX", }; @@ -350,8 +403,12 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en if (!argv || !argv[0]) return -EINVAL; - if (!env.envp) - env.envp = envp_empty; + // Set default environment + for (const struct environ* e = default_environ; e->key; e++) { + r = set_environ(&env, e->key, e->val); + if (r) + goto ERROR; + } if (!logging_callback) logging_callback = &default_logging_callback; @@ -371,25 +428,69 @@ PAKFIRE_EXPORT int pakfire_execute(Pakfire pakfire, const char* argv[], char* en if (!(flags & PAKFIRE_EXECUTE_ENABLE_NETWORK)) args.flags |= CLONE_NEWNET; + // Setup interactive environment + if (flags & PAKFIRE_EXECUTE_INTERACTIVE) { + // Set environment + r = set_environ(&env, "PS1", "pakfire-chroot \\w> "); + if (r) + goto ERROR; + + // Copy TERM + char* TERM = secure_getenv("TERM"); + if (TERM) { + r = set_environ(&env, "TERM", TERM); + if (r) + goto ERROR; + } + + // Copy LANG + char* LANG = secure_getenv("LANG"); + if (LANG) { + r = set_environ(&env, "LANG", LANG); + if (r) + goto ERROR; + } + // Make some file descriptors for stdout & stderr - if (!(flags & PAKFIRE_EXECUTE_INTERACTIVE)) { + } else { if (pipe(env.stdout) < 0) { ERROR(pakfire, "Could not create file descriptors for stdout: %s\n", strerror(errno)); - - return -errno; + r = -1; + goto ERROR; } if (pipe(env.stderr) < 0) { ERROR(pakfire, "Could not create file descriptors for stderr: %s\n", strerror(errno)); + r = -1; + goto ERROR; + } + } - return -errno; + // Copy user environment + if (envp) { + char* key; + char* val; + + // Copy environment variables + for (unsigned int i = 0; envp[i]; i++) { + r = pakfire_string_partition(envp[i], "=", &key, &val); + if (r) + continue; + + // Set value + set_environ(&env, key, val); + + if (key) + free(key); + if (val) + free(val); } } // Make cgroup name - int r = pakfire_cgroup_random_name(env.cgroup); + r = pakfire_cgroup_random_name(env.cgroup); if (r) goto ERROR; @@ -473,6 +574,10 @@ ERROR: if (env.stderr[0]) close(env.stderr[0]); + // Free environment + for (unsigned int i = 0; env.envp[i]; i++) + free(env.envp[i]); + return r; } diff --git a/src/pakfire/builder.py b/src/pakfire/builder.py index aff755a7d..20ae0f655 100644 --- a/src/pakfire/builder.py +++ b/src/pakfire/builder.py @@ -147,11 +147,7 @@ class BuilderContext(object): @property def environ(self): # Build a minimal environment for executing, but try to inherit TERM and LANG - env = { - "PS1" : "pakfire-chroot \w> ", - "TERM" : os.environ.get("TERM", "vt100"), - "LANG" : os.environ.get("LANG", "en_US.UTF-8"), - } + env = {} # Fake UTS_MACHINE, when we cannot use the personality syscall and # if the host architecture is not equal to the target architecture.