From e568a025e14273bb67c359cb6203bdae03aaa03e Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 12 Jul 2022 14:46:56 +0100 Subject: [PATCH] custom-env: Add support for argument array execve() takes the same form for arguments as environment: an array of constant pointers to mutable strings, terminated by a NULL. To make it easier for users who want to build up their own argument strings to pass to execve, add support for argument arrays to custom_env. Signed-off-by: Daniel Stone --- shared/process-util.c | 38 +++++++++++++++++++++++++++++++++++++- shared/process-util.h | 14 +++++++++++--- tests/custom-env-test.c | 19 +++++++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/shared/process-util.c b/shared/process-util.c index 1da62dcc..7cb92f6c 100644 --- a/shared/process-util.c +++ b/shared/process-util.c @@ -78,6 +78,8 @@ custom_env_init_from_environ(struct custom_env *env) wl_array_init(&env->envp); env->env_finalized = false; + wl_array_init(&env->argp); + env->arg_finalized = false; for (it = environ; *it; it++) { ep = wl_array_add(&env->envp, sizeof *ep); @@ -94,8 +96,11 @@ custom_env_fini(struct custom_env *env) wl_array_for_each(p, &env->envp) free(*p); - wl_array_release(&env->envp); + + wl_array_for_each(p, &env->argp) + free(*p); + wl_array_release(&env->argp); } static char ** @@ -116,6 +121,20 @@ custom_env_get_env_var(struct custom_env *env, const char *name) return NULL; } +void +custom_env_add_arg(struct custom_env *env, const char *arg) +{ + char **ap; + + assert(!env->arg_finalized); + + ap = wl_array_add(&env->argp, sizeof *ap); + assert(ap); + + *ap = strdup(arg); + assert(*ap); +} + void custom_env_set_env_var(struct custom_env *env, const char *name, const char *value) { @@ -151,3 +170,20 @@ custom_env_get_envp(struct custom_env *env) return env->envp.data; } + +char *const * +custom_env_get_argp(struct custom_env *env) +{ + char **ap; + + assert(!env->arg_finalized); + + /* add terminating NULL */ + ap = wl_array_add(&env->argp, sizeof *ap); + assert(ap); + *ap = NULL; + + env->arg_finalized = true; + + return env->argp.data; +} diff --git a/shared/process-util.h b/shared/process-util.h index 8f8ead7d..081ed331 100644 --- a/shared/process-util.h +++ b/shared/process-util.h @@ -61,13 +61,15 @@ fdstr_close_all(struct fdstr *s); /** - * A container for environment variables, designed to be used when forking child - * processes, as setenv() and anything which allocates memory cannot be used - * between fork() and exec(). + * A container for environment variables and/or process arguments, designed to + * be used when forking child processes, as setenv() and anything which + * allocates memory cannot be used between fork() and exec(). */ struct custom_env { struct wl_array envp; bool env_finalized; + struct wl_array argp; + bool arg_finalized; }; void @@ -79,5 +81,11 @@ custom_env_fini(struct custom_env *env); void custom_env_set_env_var(struct custom_env *env, const char *name, const char *value); +void +custom_env_add_arg(struct custom_env *env, const char *arg); + char *const * custom_env_get_envp(struct custom_env *env); + +char *const * +custom_env_get_argp(struct custom_env *env); diff --git a/tests/custom-env-test.c b/tests/custom-env-test.c index 49adb022..44e3f0f7 100644 --- a/tests/custom-env-test.c +++ b/tests/custom-env-test.c @@ -73,6 +73,8 @@ setup_env(struct weston_test_harness *harness) DECLARE_FIXTURE_SETUP(setup_env); +#define DEFAULT_ENVP (char * const []) { "ENV1=one", "ENV2=two", "ENV3=three", NULL } + TEST(basic_env) { struct custom_env env; @@ -85,3 +87,20 @@ TEST(basic_env) assert(env.env_finalized); custom_env_fini(&env); } + +TEST(basic_env_arg) +{ + struct custom_env env; + char *const argp[] = { "arg1", "arg2", "arg3", NULL }; + + custom_env_init_from_environ(&env); + custom_env_add_arg(&env, "arg1"); + custom_env_add_arg(&env, "arg2"); + custom_env_add_arg(&env, "arg3"); + + ASSERT_STR_ARRAY_MATCH("envp", custom_env_get_envp(&env), DEFAULT_ENVP); + assert(env.env_finalized); + ASSERT_STR_ARRAY_MATCH("argp", custom_env_get_argp(&env), argp); + assert(env.arg_finalized); + custom_env_fini(&env); +}