diff src/terminal.c @ 12096:0a61213afdd2 v8.0.0928

patch 8.0.0928: MS-Windows: passing arglist to job has escaping problems commit https://github.com/vim/vim/commit/dcaa61384ca76e42f7feda5640fb85b58cee03e5 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Aug 13 17:13:09 2017 +0200 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 https://github.com/vim/vim/issues/1954)
author Christian Brabandt <cb@256bit.org>
date Sun, 13 Aug 2017 17:15:03 +0200
parents 125994e132c7
children bdeb41cb755a
line wrap: on
line diff
--- 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 @@ static term_T *in_terminal_loop = NULL;
 /*
  * 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 @@ setup_job_options(jobopt_T *opt, int row
 }
 
     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_start(char_u *cmd, jobopt_T *opt, i
     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 @@ term_start(char_u *cmd, jobopt_T *opt, i
     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 @@ term_start(char_u *cmd, jobopt_T *opt, i
     void
 ex_terminal(exarg_T *eap)
 {
+    typval_T	argvar;
     jobopt_T	opt;
     char_u	*cmd;
 
@@ -468,7 +478,9 @@ ex_terminal(exarg_T *eap)
 	    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 @@ f_term_sendkeys(typval_T *argvars, typva
     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 @@ f_term_start(typval_T *argvars, typval_T
 
     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 @@ dyn_winpty_init(void)
  * 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 @@ term_and_job_init(term_T *term, int rows
     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 @@ term_and_job_init(term_T *term, int rows
     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 @@ term_report_winsize(term_T *term, int ro
  * 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;