Fix win32 command-line quoting on rust_run_program.
This commit is contained in:
parent
7c1d1d6c9a
commit
7da3733c73
1 changed files with 62 additions and 4 deletions
|
@ -5,6 +5,64 @@
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
|
bool backslash_run_ends_in_quote(char const *c) {
|
||||||
|
while (*c == '\\') ++c;
|
||||||
|
return *c == '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_first_char(char *&buf, char const *c) {
|
||||||
|
switch (*c) {
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
// Escape quotes.
|
||||||
|
*buf++ = '\\';
|
||||||
|
*buf++ = '"';
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
if (backslash_run_ends_in_quote(c)) {
|
||||||
|
// Double all backslashes that are in runs before quotes.
|
||||||
|
*buf++ = '\\';
|
||||||
|
*buf++ = '\\';
|
||||||
|
} else {
|
||||||
|
// Pass other backslashes through unescaped.
|
||||||
|
*buf++ = '\\';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*buf++ = *c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_whitespace(char const *arg) {
|
||||||
|
while (*arg) {
|
||||||
|
switch (*arg++) {
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_arg(char *& buf, char const *arg, bool last) {
|
||||||
|
bool quote = contains_whitespace(arg);
|
||||||
|
if (quote)
|
||||||
|
*buf++ = '"';
|
||||||
|
while (*arg)
|
||||||
|
append_first_char(buf, arg++);
|
||||||
|
if (quote)
|
||||||
|
*buf++ = '"';
|
||||||
|
|
||||||
|
if (! last) {
|
||||||
|
*buf++ = ' ';
|
||||||
|
} else {
|
||||||
|
*buf++ = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" CDECL int
|
extern "C" CDECL int
|
||||||
rust_run_program(const char* argv[], int in_fd, int out_fd, int err_fd) {
|
rust_run_program(const char* argv[], int in_fd, int out_fd, int err_fd) {
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
|
@ -29,14 +87,14 @@ rust_run_program(const char* argv[], int in_fd, int out_fd, int err_fd) {
|
||||||
size_t cmd_len = 0;
|
size_t cmd_len = 0;
|
||||||
for (const char** arg = argv; *arg; arg++) {
|
for (const char** arg = argv; *arg; arg++) {
|
||||||
cmd_len += strlen(*arg);
|
cmd_len += strlen(*arg);
|
||||||
cmd_len++; // Space or \0
|
cmd_len += 3; // Two quotes plus trailing space or \0
|
||||||
}
|
}
|
||||||
|
cmd_len *= 2; // Potentially backslash-escape everything.
|
||||||
|
|
||||||
char* cmd = (char*)malloc(cmd_len);
|
char* cmd = (char*)malloc(cmd_len);
|
||||||
char* pos = cmd;
|
char* pos = cmd;
|
||||||
for (const char** arg = argv; *arg; arg++) {
|
for (const char** arg = argv; *arg; arg++) {
|
||||||
strcpy(pos, *arg);
|
append_arg(pos, *arg, *(arg+1) == NULL);
|
||||||
pos += strlen(*arg);
|
|
||||||
if (*(arg+1)) *(pos++) = ' ';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue