summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDavid Wragg <david@rabbitmq.com>2010-10-27 23:12:59 +0100
committerDavid Wragg <david@rabbitmq.com>2010-10-27 23:12:59 +0100
commit692c9b9cb21ab6ed799f7ae0dc9347f75ae7fe50 (patch)
tree147912ddb8b53e6ebd5ba5d56a339da23928f487 /tools
parent972c146985ffa9209b53d9f31a4920730f2773b4 (diff)
downloadrabbitmq-c-github-ask-692c9b9cb21ab6ed799f7ae0dc9347f75ae7fe50.tar.gz
Construct the command line to conform to Windows escaping conventions
Those conventions are crazier than I thought. I leaned about this from <http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx>.
Diffstat (limited to 'tools')
-rw-r--r--tools/windows/process.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/tools/windows/process.c b/tools/windows/process.c
index 0a005bd..d0e162a 100644
--- a/tools/windows/process.c
+++ b/tools/windows/process.c
@@ -98,37 +98,57 @@ static char *make_command_line(const char *const *argv)
dest = buf = malloc(len);
if (!buf)
die("allocating memory for subprocess command line");
-
- *dest++ = '\"';
+
+ /* Here we perform the inverse of the CommandLineToArgvW
+ function. Note that it's rules are slightly crazy: A
+ sequence of backslashes only act to escape if followed by
+ double quotes. A seuqence of backslashes not followed by
+ double quotes is unaffected. */
for (i = 0;;) {
const char *src = argv[i];
+ int backslashes = 0;
+
+ *dest++ = '\"';
+
for (;;) {
switch (*src) {
case 0:
goto done;
case '\"':
+ for (; backslashes; backslashes--)
+ *dest++ = '\\';
+
+ *dest++ = '\\';
+ *dest++ = '\"';
+ break;
+
case '\\':
+ backslashes++;
*dest++ = '\\';
- /* fall through */
+ break;
default:
- *dest++ = *src++;
+ backslashes = 0;
+ *dest++ = *src;
break;
}
+
+ src++;
}
- done:
+ done:
+ for (; backslashes; backslashes--)
+ *dest++ = '\\';
+
+ *dest++ = '\"';
if (!argv[++i])
break;
- *dest++ = '\"';
*dest++ = ' ';
- *dest++ = '\"';
}
- *dest++ = '\"';
*dest++ = 0;
return buf;
}