aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--win32/process.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/win32/process.c b/win32/process.c
index a70b9484e..e7c9ca187 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -109,38 +109,34 @@ parse_interpreter(const char *cmd, interp_t *interp)
109char * FAST_FUNC 109char * FAST_FUNC
110quote_arg(const char *arg) 110quote_arg(const char *arg)
111{ 111{
112 char *r = xmalloc(2 * strlen(arg) + 3); // max-esc, enclosing DQ, \0 112 char *d, *r = xmalloc(2 * strlen(arg) + 3); // max-esc, quotes, \0
113 char *d = r; 113 size_t nbs = 0; // consecutive backslashes before current char
114 int nbs = 0; // n consecutive BS right before current char 114 int quoted = !*arg;
115 115
116 /* empty arguments and those containing tab/space must be quoted */ 116 for (d = r; *arg; *d++ = *arg++) {
117 if (!*arg || strpbrk(arg, " \t")) { 117 if (*arg == ' ' || *arg == '\t')
118 *d++ = '"'; 118 quoted = 1;
119 } 119
120 if (*arg == '\\' || *arg == '"')
121 *d++ = '\\';
122 else
123 d -= nbs; // undo nbs escapes, if any (not followed by DQ)
120 124
121 while (*arg) { 125 if (*arg == '\\')
122 switch (*arg) {
123 case '\\':
124 ++nbs; 126 ++nbs;
125 break; 127 else
126 case '"': // double consecutive-BS, plus one to escape the DQ
127 for (++nbs; nbs; --nbs)
128 *d++ = '\\';
129 break;
130 default: // reset count if followed by not-DQ
131 nbs = 0; 128 nbs = 0;
132 }
133 *d++ = *arg++;
134 } 129 }
135 130
136 if (*r == '"') { 131 if (quoted) {
137 while (nbs--) // double consecutive-BS before the closing DQ 132 memmove(r + 1, r, d++ - r);
138 *d++ = '\\'; 133 *r = *d++ = '"';
139 *d++ = '"'; 134 } else {
135 d -= nbs;
140 } 136 }
141 *d++ = '\0';
142 137
143 return xrealloc(r, d - r); 138 *d = 0;
139 return r;
144} 140}
145 141
146char * FAST_FUNC 142char * FAST_FUNC