[lxc-devel] [lxc/master] implement lxc_string_split_quoted

hallyn on Github lxc-bot at linuxcontainers.org
Wed Oct 4 06:00:13 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 766 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171004/0fd8a9b4/attachment.bin>
-------------- next part --------------
From c47e94c9bc11b192fe592234da1c4a0849746d25 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <shallyn at cisco.com>
Date: Wed, 4 Oct 2017 05:14:00 +0000
Subject: [PATCH] implement lxc_string_split_quoted

lxc_string_split_quoted() splits a string on spaces, but keeps
groups in single or double qoutes together.  In other words,
generally what we'd want for argv behavior.

Switch lxc-execute to use this for lxc.execute.cmd.

Switch lxc-oci template to put the lxc.execute.cmd inside single
quotes, because parse_line() will eat those.  If we don't do that,
then if we have lxc.execute.cmd = /bin/echo "hello, world", then the
last double quote will disappear.
---
 src/lxc/tools/lxc_execute.c |  5 +---
 src/lxc/utils.c             | 68 +++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/utils.h             |  1 +
 templates/lxc-oci.in        |  2 +-
 4 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c
index f69ab6a51..234591c47 100644
--- a/src/lxc/tools/lxc_execute.c
+++ b/src/lxc/tools/lxc_execute.c
@@ -99,10 +99,7 @@ static bool set_argv(struct lxc_conf *conf, struct lxc_arguments *args)
 	if (!conf->execute_cmd)
 		return false;
 
-	/* TODO -
-	   we should honor '"' etc; This seems worth a new helper in utils.c.
-	 */
-	components = lxc_string_split(conf->execute_cmd, ' ');
+	components = lxc_string_split_quoted(conf->execute_cmd);
 	if (!components)
 		return false;
 
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index e6a44a516..c9a60979a 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -816,6 +816,74 @@ char **lxc_string_split(const char *string, char _sep)
 	return NULL;
 }
 
+static bool complete_word(char ***result, char *start, char *end, size_t *cap, size_t *cnt)
+{
+	int r;
+
+	r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16);
+	if (r < 0)
+		return false;
+	(*result)[*cnt] = strndup(start, end - start);
+	if (!(*result)[*cnt])
+		return false;
+	(*cnt)++;
+
+	return true;
+}
+
+/*
+ * Given a a string 'one two "three four"', split into three words,
+ * one, two, and "three four"
+ */
+char **lxc_string_split_quoted(char *string)
+{
+	char *nextword = string, *p, state;
+	char **result = NULL;
+	size_t result_capacity = 0;
+	size_t result_count = 0;
+
+	if (!string || !*string)
+		return calloc(1, sizeof(char *));
+
+	// TODO I'm *not* handling escaped quote
+	state = ' ';
+	for (p = string; *p; p++) {
+		switch(state) {
+		case ' ':
+			if (isspace(*p))
+				continue;
+			else if (*p == '"' || *p == '\'') {
+				nextword = p;
+				state = *p;
+				continue;
+			}
+			nextword = p;
+			state = 'a';
+			continue;
+		case 'a':
+			if (isspace(*p)) {
+				complete_word(&result, nextword, p, &result_capacity, &result_count);
+				state = ' ';
+				continue;
+			}
+			continue;
+		case '"':
+		case '\'':
+			if (*p == state) {
+				complete_word(&result, nextword+1, p, &result_capacity, &result_count);
+				state = ' ';
+				continue;
+			}
+			continue;
+		}
+	}
+
+	if (state == 'a')
+		complete_word(&result, nextword, p, &result_capacity, &result_count);
+
+	return realloc(result, (result_count + 1) * sizeof(char *));
+}
+
 char **lxc_string_split_and_trim(const char *string, char _sep)
 {
 	char *token, *str, *saveptr = NULL;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index e83ed49eb..833ec4416 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -292,6 +292,7 @@ extern bool lxc_string_in_list(const char *needle, const char *haystack,
 			       char sep);
 extern char **lxc_string_split(const char *string, char sep);
 extern char **lxc_string_split_and_trim(const char *string, char sep);
+extern char **lxc_string_split_quoted(char *string);
 /* Append string to NULL-terminated string array. */
 extern int lxc_append_string(char ***list, char *entry);
 
diff --git a/templates/lxc-oci.in b/templates/lxc-oci.in
index f715125f7..c2cfb351a 100755
--- a/templates/lxc-oci.in
+++ b/templates/lxc-oci.in
@@ -197,7 +197,7 @@ entrypoint=$(getep ${DOWNLOAD_TEMP} latest)
 rm -rf "${LXC_ROOTFS}.tmp"
 
 LXC_CONF_FILE="${LXC_PATH}/config"
-echo "lxc.execute.cmd = ${entrypoint}" >> "${LXC_CONF_FILE}"
+echo "lxc.execute.cmd = '${entrypoint}'" >> "${LXC_CONF_FILE}"
 echo "lxc.mount.auto = proc:mixed sys:mixed cgroup:mixed" >> "${LXC_CONF_FILE}"
 
 echo "lxc.uts.name = ${LXC_NAME}" >> ${LXC_PATH}/config


More information about the lxc-devel mailing list