From 32ae26e519eeb6a5108f1d82fe36ce5b6ef65af3 Mon Sep 17 00:00:00 2001
From: Mikkel Oscar Lyderik <mikkeloscar@gmail.com>
Date: Mon, 25 Jan 2016 00:02:28 +0100
Subject: [PATCH] Add quotes to multiword arguments.

This adds quotes around multiword arguments before they are passed to
`/bin/sh -c` in an exec command.

Example:

I connect to irc like this:

    exec termite -e "mosh server tmux a"

Without this patch the arguments are passed to sh as:

    termite -e mosh server tmux a

When it should be:

    termite -e "mosh server tmux a"

For the command to work.
---
 common/stringop.c  | 26 ++++++++++++++++++++++++++
 include/stringop.h |  5 +++++
 sway/commands.c    |  2 ++
 3 files changed, 33 insertions(+)

diff --git a/common/stringop.c b/common/stringop.c
index 81d9b963e..186fe1211 100644
--- a/common/stringop.c
+++ b/common/stringop.c
@@ -273,6 +273,32 @@ char *join_args(char **argv, int argc) {
 	return res;
 }
 
+static bool has_whitespace(const char *str) {
+	while (*str) {
+		if (isspace(*str)) {
+			return true;
+		}
+		++str;
+	}
+	return false;
+}
+
+/**
+ * Add quotes around any argv with whitespaces.
+ */
+void add_quotes(char **argv, int argc) {
+	int i;
+	for (i = 0; i < argc; ++i) {
+		if (has_whitespace(argv[i])) {
+			int len = strlen(argv[i]) + 3;
+			char *tmp = argv[i];
+			argv[i] = malloc(len * sizeof(char));
+			snprintf(argv[i], len, "\"%s\"", tmp);
+			free(tmp);
+		}
+	}
+}
+
 /*
  * Join a list of strings, adding separator in between. Separator can be NULL.
  */
diff --git a/include/stringop.h b/include/stringop.h
index bb681bcdb..7c29a745e 100644
--- a/include/stringop.h
+++ b/include/stringop.h
@@ -31,6 +31,11 @@ int unescape_string(char *string);
 char *join_args(char **argv, int argc);
 char *join_list(list_t *list, char *separator);
 
+/**
+ * Add quotes around any argv with whitespaces.
+ */
+void add_quotes(char **argv, int argc);
+
 // split string into 2 by delim.
 char *cmdsep(char **stringp, const char *delim);
 // Split string into 2 by delim, handle quotes
diff --git a/sway/commands.c b/sway/commands.c
index 9f6e50327..ae5c48e64 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -361,8 +361,10 @@ static struct cmd_results *cmd_exec_always(int argc, char **argv) {
 			return error;
 		}
 
+		add_quotes(argv + 1, argc - 1);
 		tmp = join_args(argv + 1, argc - 1);
 	} else {
+		add_quotes(argv, argc);
 		tmp = join_args(argv, argc);
 	}