diff options
author | Daniel Stone <daniels@collabora.com> | 2022-07-12 16:21:39 +0100 |
---|---|---|
committer | Pekka Paalanen <pq@iki.fi> | 2022-07-19 14:12:37 +0000 |
commit | 2cdb473690a4414b0bcafbb3878e468fce6e89e2 (patch) | |
tree | 05d5335e1ff9290f7a229b586e38742c2f395a06 /shared | |
parent | e568a025e14273bb67c359cb6203bdae03aaa03e (diff) |
custom-env: Add helper to parse combined env/arg strings
Users like desktop-shell want to parse a provided string containing a
combination of environment and arg, e.g.: ENV=stuff /path/to/thing --good
Add support to custom-env for parsing this, with tests, so we can delete
the custom implementation inside desktop-shell.
Signed-off-by: Daniel Stone <daniels@collabora.com>
Diffstat (limited to 'shared')
-rw-r--r-- | shared/process-util.c | 81 | ||||
-rw-r--r-- | shared/process-util.h | 3 |
2 files changed, 84 insertions, 0 deletions
diff --git a/shared/process-util.c b/shared/process-util.c index 7cb92f6c..e36c6470 100644 --- a/shared/process-util.c +++ b/shared/process-util.c @@ -25,6 +25,9 @@ #include "config.h" +#include <assert.h> +#include <ctype.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -154,6 +157,84 @@ custom_env_set_env_var(struct custom_env *env, const char *name, const char *val assert(*ep); } +/** + * Add information from a parsed exec string to a custom_env + * + * An 'exec string' is a string in the format: + * ENVFOO=bar ENVBAR=baz /path/to/exec --arg anotherarg + * + * This function will parse such a string and add the specified environment + * variables (in the format KEY=value) up until it sees a non-environment + * string, after which point every entry will be interpreted as a new + * argument. + * + * Entries are space-separated; there is no support for quoting. + */ +void +custom_env_add_from_exec_string(struct custom_env *env, const char *exec_str) +{ + char *dup_path = strdup(exec_str); + char *start = dup_path; + + assert(dup_path); + + /* Build the environment array (if any) by handling any number of + * equal-separated key=value at the start of the string, split by + * spaces; uses "foo=bar baz=quux meh argh" as the example, where + * "foo=bar" and "baz=quux" should go into the environment, and + * "meh" should be executed with "argh" as its first argument */ + while (*start) { + char *k = NULL, *v = NULL; + char *p; + + /* Leaves us with "foo\0bar baz=quux meh argh", with k pointing + * to "foo" and v pointing to "bar baz=quux meh argh" */ + for (p = start; *p && !isspace(*p); p++) { + if (*p == '=') { + *p++ = '\0'; + k = start; + v = p; + break; + } + } + + if (!v) + break; + + /* Walk to the next space or NUL, filling any trailing spaces + * with NUL, to give us "foo\0bar\0\0baz=quux meh argh". + * k will point to "foo", v will point to "bar", and + * start will point to "baz=quux meh argh". */ + while (*p && !isspace(*p)) + p++; + while (*p && isspace(*p)) + *p++ = '\0'; + start = p; + + custom_env_set_env_var(env, k, v); + } + + /* Now build the argv array by splitting on spaces */ + while (*start) { + char *p; + bool valid = false; + + for (p = start; *p && !isspace(*p); p++) + valid = true; + + if (!valid) + break; + + while (*p && isspace(*p)) + *p++ = '\0'; + + custom_env_add_arg(env, start); + start = p; + } + + free(dup_path); +} + char *const * custom_env_get_envp(struct custom_env *env) { diff --git a/shared/process-util.h b/shared/process-util.h index 081ed331..05543f6f 100644 --- a/shared/process-util.h +++ b/shared/process-util.h @@ -84,6 +84,9 @@ custom_env_set_env_var(struct custom_env *env, const char *name, const char *val void custom_env_add_arg(struct custom_env *env, const char *arg); +void +custom_env_add_from_exec_string(struct custom_env *env, const char *exec_str); + char *const * custom_env_get_envp(struct custom_env *env); |