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:<name>`
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 <joe@benden.us>
This commit is contained in:
Joseph Benden 2020-11-19 16:37:29 -07:00
parent f5ca4c26ac
commit 707da6f2d2
No known key found for this signature in database
GPG key ID: 713DC1002C5879C2
6 changed files with 103 additions and 0 deletions

View file

@ -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;

View file

@ -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 },

58
sway/commands/export.c Normal file
View file

@ -0,0 +1,58 @@
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE 1
#define __BSD_VISIBLE 1
#include <stdio.h>
#include <string.h>
#include <strings.h>
#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);
}

View file

@ -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];

View file

@ -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',

View file

@ -586,6 +586,21 @@ The default colors are:
*exec_always* <shell command>
Like *exec*, but the shell command will be executed _again_ after *reload*.
*export* <name> <value>
Sets the Wayland session environment variable _name_ to a specific
_value_. All environment variables are available in the config
using the _$ENV:<name>_ 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* <width> x <height>
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