diff --git a/include/env.h b/include/env.h index e91328327..16a811a4c 100644 --- a/include/env.h +++ b/include/env.h @@ -19,4 +19,10 @@ char **env_create(); */ char **env_setenv(char **envp, char *name, char *value); +/** + * Unsets an environment variable in the given environment. + * If successful, this will reallocate the entire array. + */ +char **env_unsetenv(char **envp, char *name); + #endif diff --git a/include/sway/commands.h b/include/sway/commands.h index b77f49221..e933b3728 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -126,6 +126,7 @@ sway_cmd cmd_default_border; sway_cmd cmd_default_floating_border; sway_cmd cmd_default_orientation; sway_cmd cmd_env; +sway_cmd cmd_env_unset; sway_cmd cmd_exec; sway_cmd cmd_exec_always; sway_cmd cmd_exit; diff --git a/sway/commands.c b/sway/commands.c index b07a6a8cf..e19f86867 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -58,6 +58,7 @@ static const struct cmd_handler handlers[] = { { "default_border", cmd_default_border }, { "default_floating_border", cmd_default_floating_border }, { "env", cmd_env }, + { "env_unset", cmd_env_unset }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "floating_maximum_size", cmd_floating_maximum_size }, diff --git a/sway/commands/env.c b/sway/commands/env.c index 7032a59e2..aba4e33b2 100644 --- a/sway/commands/env.c +++ b/sway/commands/env.c @@ -15,3 +15,14 @@ struct cmd_results *cmd_env(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL); } + +struct cmd_results *cmd_env_unset(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "env_unset", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + child_envp = env_unsetenv(child_envp, argv[0]); + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/env.c b/sway/env.c index 12843fe33..8c7d63c24 100644 --- a/sway/env.c +++ b/sway/env.c @@ -51,18 +51,25 @@ size_t env_len(char **envp) { return i; } -char **env_clone(char **envp, size_t reserve) { - char **new_envp = calloc(env_len(envp) + 1 + reserve, sizeof(char *)); +char **env_clone(char **envp, size_t reserve, env_info exclude) { + size_t elem_count = env_len(envp) + 1 + reserve - (exclude.ptr != NULL); + char **new_envp = calloc(elem_count, sizeof(char *)); char *strp; size_t i = 0; + size_t new_i = 0; while ((strp = envp[i]) != NULL) { + if (exclude.ptr == strp) { + i++; + continue; + } size_t n = strlen(strp) + 1; char *new_strp = malloc(n); memcpy(new_strp, strp, n); - new_envp[i] = new_strp; + new_envp[new_i] = new_strp; i++; + new_i++; } return new_envp; @@ -81,7 +88,7 @@ void env_destroy(char **envp) { // copy the global environment array into a newly-allocated one // you are responsible for deallocating it after use -char **env_create() { return env_clone(environ, 0); } +char **env_create() { return env_clone(environ, 0, (env_info){NULL, 0}); } // use env_get_envp() to acquire an envp // might clone and deallocate the given envp @@ -100,9 +107,19 @@ char **env_setenv(char **envp, char *name, char *value) { envp[existing.idx] = newp; return envp; } else { - char **new_envp = env_clone(envp, 1); + char **new_envp = env_clone(envp, 1, (env_info){NULL, 0}); new_envp[env_len(envp)] = newp; env_destroy(envp); return new_envp; } } + +char **env_unsetenv(char **envp, char *name) { + env_info existing = env_get(envp, name); + if (existing.ptr == NULL) // dont do anything if + return envp; // the variable is not set + + char **new_envp = env_clone(envp, 0, existing); + env_destroy(envp); + return new_envp; +}