Mercurial > vim
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;