From afe666fd6ed3232aee0bd8bf5fa062b980190ee8 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Wed, 30 Jun 2021 19:56:31 +0100 Subject: [PATCH] action: expand shell variables before execvp() Expanding shell variables, including tilde, enables the following type of keybind: bash ~/mute-script.sh Fixes issue #32 --- include/common/buf.h | 13 ++++++++++--- src/action.c | 7 ++++++- src/common/buf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/include/common/buf.h b/include/common/buf.h index 98be625d..bb18624d 100644 --- a/include/common/buf.h +++ b/include/common/buf.h @@ -17,17 +17,24 @@ struct buf { int len; }; +/** + * buf_expand_shell_variables - expand $foo and ~ in buffer + * @s: buffer + * Note: ${foo} and $$ are not handled + */ +void buf_expand_shell_variables(struct buf *s); + /** * buf_init - allocate NULL-terminated C string buffer - * @s - buffer + * @s: buffer * Note: use free(s->buf) to free it. */ void buf_init(struct buf *s); /** * buf_add - add data to C string buffer - * @s - buffer - * @data - data to be added + * @s: buffer + * @data: data to be added */ void buf_add(struct buf *s, const char *data); diff --git a/src/action.c b/src/action.c index 5510dc85..3ac0633d 100644 --- a/src/action.c +++ b/src/action.c @@ -26,7 +26,12 @@ action(struct server *server, const char *action, const char *command) if (!strcasecmp(action, "Debug")) { /* nothing */ } else if (!strcasecmp(action, "Execute")) { - spawn_async_no_shell(command); + struct buf cmd; + buf_init(&cmd); + buf_add(&cmd, command); + buf_expand_shell_variables(&cmd); + spawn_async_no_shell(cmd.buf); + free(cmd.buf); } else if (!strcasecmp(action, "Exit")) { wl_display_terminate(server->wl_display); } else if (!strcasecmp(action, "NextWindow")) { diff --git a/src/common/buf.c b/src/common/buf.c index 27081f01..abc2b877 100644 --- a/src/common/buf.c +++ b/src/common/buf.c @@ -1,5 +1,49 @@ +#include #include "common/buf.h" +void +buf_expand_shell_variables(struct buf *s) +{ + struct buf new; + struct buf environment_variable; + buf_init(&new); + buf_init(&environment_variable); + + for (int i = 0 ; i < s->len ; i++) { + if (s->buf[i] == '$') { + /* expand environment variable */ + environment_variable.len = 0; + buf_add(&environment_variable, s->buf + i + 1); + char *p = environment_variable.buf; + while (isalnum(*p)) { + ++p; + } + *p = '\0'; + p = getenv(environment_variable.buf); + if (!p) { + goto out; + } + buf_add(&new, p); + i += strlen(environment_variable.buf); + } else if (s->buf[i] == '~') { + /* expand tilde */ + buf_add(&new, getenv("HOME")); + } else { + /* just add one character at a time */ + if (new.alloc <= new.len + 1) { + new.alloc = new.alloc * 3/2 + 16; + new.buf = realloc(new.buf, new.alloc); + } + new.buf[new.len++] = s->buf[i]; + new.buf[new.len] = '\0'; + } + } +out: + free(environment_variable.buf); + free(s->buf); + s->buf = new.buf; +} + void buf_init(struct buf *s) { -- 2.52.0