From 707da6f2d20a821a830914819e636b79d14d25a4 Mon Sep 17 00:00:00 2001 From: Joseph Benden Date: Thu, 19 Nov 2020 16:37:29 -0700 Subject: [PATCH] commands: Add export command The `export` command allows one to set environment variables easily within their configuration. It additionally allows one to get an environment variable using the `$ENV:` syntax. With the configuration snippet listed below, which MUST appear before any `exec` commands -- so that environment variables are all available to these newly launched programs -- set a number of variables used by GTK & Qt for forcing Wayland rendering. ``` export GDK_BACKEND wayland export CLUTTER_BACKEND wayland export MOZ_ENABLE_WAYLAND 1 export QT_QPA_PLATFORM wayland-egl export QT_WAYLAND_DISABLE_WINDOWDECORATION 1 export ELM_DISPLAY wl export _JAVA_AWT_WM_NONREPARENTING 0 export SDL_VIDEODRIVER wayland ``` While the above does not demonstrate reading variables, the example below does demonstrates its use: ``` export PATH $ENV:HOME/bin:$ENV:PATH ``` Signed-off-by: Joseph Benden --- include/sway/commands.h | 1 + sway/commands.c | 1 + sway/commands/export.c | 58 +++++++++++++++++++++++++++++++++++++++++ sway/config.c | 27 +++++++++++++++++++ sway/meson.build | 1 + sway/sway.5.scd | 15 +++++++++++ 6 files changed, 103 insertions(+) create mode 100644 sway/commands/export.c diff --git a/include/sway/commands.h b/include/sway/commands.h index 964b3661..50e1f2d7 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -123,6 +123,7 @@ sway_cmd cmd_default_floating_border; sway_cmd cmd_default_orientation; sway_cmd cmd_exec; sway_cmd cmd_exec_always; +sway_cmd cmd_export; sway_cmd cmd_exit; sway_cmd cmd_floating; sway_cmd cmd_floating_maximum_size; diff --git a/sway/commands.c b/sway/commands.c index fe1e98b5..30e2b2ac 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -58,6 +58,7 @@ static struct cmd_handler handlers[] = { { "default_floating_border", cmd_default_floating_border }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, + { "export", cmd_export }, { "floating_maximum_size", cmd_floating_maximum_size }, { "floating_minimum_size", cmd_floating_minimum_size }, { "floating_modifier", cmd_floating_modifier }, diff --git a/sway/commands/export.c b/sway/commands/export.c new file mode 100644 index 00000000..ff849c1e --- /dev/null +++ b/sway/commands/export.c @@ -0,0 +1,58 @@ +#define _POSIX_C_SOURCE 200809L +#define _GNU_SOURCE 1 +#define __BSD_VISIBLE 1 +#include +#include +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "list.h" +#include "log.h" +#include "stringop.h" + +// sort in order of longest->shortest +static int compare_set_qsort(const void *_l, const void *_r) { + struct sway_variable const *l = *(void **)_l; + struct sway_variable const *r = *(void **)_r; + return strlen(r->name) - strlen(l->name); +} + +// export TERM xterm-256color +struct cmd_results *cmd_export(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "export", EXPECTED_AT_LEAST, 2))) { + return error; + } + + char *search_var; + if (asprintf(&search_var, "$ENV:%s", argv[0]) < 0) { + return cmd_results_new(CMD_FAILURE, "Unable to allocate search variable"); + } + + struct sway_variable *var = NULL; + // Find old variable if it exists + int i; + for (i = 0; i < config->symbols->length; ++i) { + var = config->symbols->items[i]; + if (strcmp(var->name, search_var) == 0) { + break; + } + var = NULL; + } + if (var) { + free(var->value); + } else { + var = malloc(sizeof(struct sway_variable)); + if (!var) { + return cmd_results_new(CMD_FAILURE, "Unable to allocate variable"); + } + var->name = strdup(search_var); + list_add(config->symbols, var); + list_qsort(config->symbols, compare_set_qsort); + } + var->value = join_args(argv + 1, argc - 1); + // NOTE(jbenden): Should an empty string mean to unsetenv? + if (setenv(argv[0], var->value, true) != 0) + return cmd_results_new(CMD_FAILURE, "Unable to set environment variable"); + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/config.c b/sway/config.c index 71382b86..a894a60a 100644 --- a/sway/config.c +++ b/sway/config.c @@ -919,6 +919,33 @@ char *do_var_replacement(char *str) { ++find; continue; } + // Is an environment variable requested? + if (strncmp(find, "$ENV:", strlen("$ENV:")) == 0) { + char *var_name = &find[5]; + int vnlen = strlen(var_name); + if (var_name[0] == '\0') continue; + char *env_value = getenv(var_name); + if (env_value) { + int vvlen = strlen(env_value); + char *newstr = malloc(strlen(str) - (strlen("$ENV:") + vnlen) + vvlen + 1); + if (!newstr) { + sway_log(SWAY_ERROR, + "Unable to allocate replacement " + "during variable expansion"); + continue; + } + char *newptr = newstr; + int offset = find - str; + strncpy(newptr, str, offset); + newptr += offset; + strncpy(newptr, env_value, vvlen); + newptr += vvlen; + strcpy(newptr, find + vnlen + strlen("$ENV:")); + free(str); + str = newstr; + find = str + offset + vvlen; + } + } // Find matching variable for (i = 0; i < config->symbols->length; ++i) { struct sway_variable *var = config->symbols->items[i]; diff --git a/sway/meson.build b/sway/meson.build index 6e138101..bdf4cece 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -51,6 +51,7 @@ sway_sources = files( 'commands/exit.c', 'commands/exec.c', 'commands/exec_always.c', + 'commands/export.c', 'commands/floating.c', 'commands/floating_minmax_size.c', 'commands/floating_modifier.c', diff --git a/sway/sway.5.scd b/sway/sway.5.scd index f608ad2e..53167469 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -586,6 +586,21 @@ The default colors are: *exec_always* Like *exec*, but the shell command will be executed _again_ after *reload*. +*export* + Sets the Wayland session environment variable _name_ to a specific + _value_. All environment variables are available in the config + using the _$ENV:_ syntax. + + Example: +``` + export CLUTTER_BACKEND wayland + export GDK_BACKEND wayland + export MOZ_ENABLE_WAYLAND 1 + export PATH $ENV:HOME/bin:$ENV:PATH + export QT_QPA_PLATFORM wayland-egl + export QT_WAYLAND_DISABLE_WINDOWDECORATION 1 +``` + *floating_maximum_size* x Specifies the maximum size of floating windows. -1 x -1 removes the upper limit. The default is 0 x 0, which will use the width and height of the