patch 8.0.0928: MS-Windows: passing arglist to job has escaping problems
Problem: MS-Windows: passing arglist to job has escaping problems.
Solution: Improve escaping. (Yasuhiro Matsumoto, closes #1954)
diff --git a/src/terminal.c b/src/terminal.c
index 0024d5f..0267e5f 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -39,7 +39,6 @@
*
* TODO:
* - Make argument list work on MS-Windows. #1954
- * - MS-Windows: no redraw for 'updatetime' #1915
* - To set BS correctly, check get_stty(); Pass the fd of the pty.
* For the GUI fill termios with default values, perhaps like pangoterm:
* http://bazaar.launchpad.net/~leonerd/pangoterm/trunk/view/head:/main.c#L134
@@ -165,7 +164,8 @@
/*
* Functions with separate implementation for MS-Windows and Unix-like systems.
*/
-static int term_and_job_init(term_T *term, int rows, int cols, char_u *cmd, jobopt_T *opt);
+static int term_and_job_init(term_T *term, int rows, int cols,
+ typval_T *argvar, jobopt_T *opt);
static void term_report_winsize(term_T *term, int rows, int cols);
static void term_free_vterm(term_T *term);
@@ -244,7 +244,7 @@
}
static void
-term_start(char_u *cmd, jobopt_T *opt, int forceit)
+term_start(typval_T *argvar, jobopt_T *opt, int forceit)
{
exarg_T split_ea;
win_T *old_curwin = curwin;
@@ -340,16 +340,25 @@
term->tl_next = first_term;
first_term = term;
- if (cmd == NULL || *cmd == NUL)
- cmd = p_sh;
-
if (opt->jo_term_name != NULL)
curbuf->b_ffname = vim_strsave(opt->jo_term_name);
else
{
int i;
- size_t len = STRLEN(cmd) + 10;
- char_u *p = alloc((int)len);
+ size_t len;
+ char_u *cmd, *p;
+
+ if (argvar->v_type == VAR_STRING)
+ cmd = argvar->vval.v_string;
+ else if (argvar->v_type != VAR_LIST
+ || argvar->vval.v_list == NULL
+ || argvar->vval.v_list->lv_len < 1)
+ cmd = (char_u*)"";
+ else
+ cmd = get_tv_string_chk(&argvar->vval.v_list->lv_first->li_tv);
+
+ len = STRLEN(cmd) + 10;
+ p = alloc((int)len);
for (i = 0; p != NULL; ++i)
{
@@ -386,7 +395,7 @@
setup_job_options(opt, term->tl_rows, term->tl_cols);
/* System dependent: setup the vterm and start the job in it. */
- if (term_and_job_init(term, term->tl_rows, term->tl_cols, cmd, opt) == OK)
+ if (term_and_job_init(term, term->tl_rows, term->tl_cols, argvar, opt) == OK)
{
/* Get and remember the size we ended up with. Update the pty. */
vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
@@ -425,6 +434,7 @@
void
ex_terminal(exarg_T *eap)
{
+ typval_T argvar;
jobopt_T opt;
char_u *cmd;
@@ -468,7 +478,9 @@
opt.jo_term_rows = eap->line2;
}
- term_start(cmd, &opt, eap->forceit);
+ argvar.v_type = VAR_STRING;
+ argvar.vval.v_string = cmd;
+ term_start(&argvar, &opt, eap->forceit);
}
/*
@@ -2585,11 +2597,8 @@
void
f_term_start(typval_T *argvars, typval_T *rettv)
{
- char_u *cmd = get_tv_string_chk(&argvars[0]);
jobopt_T opt;
- if (cmd == NULL)
- return;
init_job_options(&opt);
/* TODO: allow more job options */
if (argvars[1].v_type != VAR_UNKNOWN
@@ -2603,7 +2612,7 @@
if (opt.jo_vertical)
cmdmod.split = WSP_VERT;
- term_start(cmd, &opt, FALSE);
+ term_start(&argvars[0], &opt, FALSE);
if (curbuf->b_term != NULL)
rettv->vval.v_number = curbuf->b_fnum;
@@ -2749,9 +2758,9 @@
* Return OK or FAIL.
*/
static int
-term_and_job_init(term_T *term, int rows, int cols, char_u *cmd, jobopt_T *opt)
+term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
{
- WCHAR *p;
+ WCHAR *p = NULL;
channel_T *channel = NULL;
job_T *job = NULL;
DWORD error;
@@ -2759,10 +2768,22 @@
void *winpty_err;
void *spawn_config = NULL;
char buf[MAX_PATH];
+ garray_T ga;
+ char_u *cmd;
if (!dyn_winpty_init())
return FAIL;
+ if (argvar->v_type == VAR_STRING)
+ cmd = argvar->vval.v_string;
+ else
+ {
+ ga_init2(&ga, (int)sizeof(char*), 20);
+ if (win32_build_cmd(argvar->vval.v_list, &ga) == FAIL)
+ goto failed;
+ cmd = ga.ga_data;
+ }
+
p = enc_to_utf16(cmd, NULL);
if (p == NULL)
return FAIL;
@@ -2855,9 +2876,12 @@
return OK;
failed:
+ if (argvar->v_type == VAR_LIST)
+ vim_free(ga.ga_data);
+ if (p != NULL)
+ vim_free(p);
if (spawn_config != NULL)
winpty_spawn_config_free(spawn_config);
- vim_free(p);
if (channel != NULL)
channel_clear(channel);
if (job != NULL)
@@ -2924,17 +2948,12 @@
* Return OK or FAIL.
*/
static int
-term_and_job_init(term_T *term, int rows, int cols, char_u *cmd, jobopt_T *opt)
+term_and_job_init(term_T *term, int rows, int cols, typval_T *argvar, jobopt_T *opt)
{
- typval_T argvars[2];
-
create_vterm(term, rows, cols);
/* TODO: if the command is "NONE" only create a pty. */
- argvars[0].v_type = VAR_STRING;
- argvars[0].vval.v_string = cmd;
-
- term->tl_job = job_start(argvars, opt);
+ term->tl_job = job_start(argvar, opt);
if (term->tl_job != NULL)
++term->tl_job->jv_refcount;