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);
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")) {
+#include <ctype.h>
#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)
{