1
0
forked from aniani/vim

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)
This commit is contained in:
Bram Moolenaar
2017-08-13 17:13:09 +02:00
parent 274a52fd58
commit dcaa61384c
6 changed files with 226 additions and 80 deletions

View File

@@ -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 rows, int cols)
}
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, int forceit)
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, int forceit)
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, int forceit)
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, typval_T *rettv)
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 *rettv)
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, int cols, char_u *cmd, jobopt_T *opt)
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, int cols, char_u *cmd, jobopt_T *opt)
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 rows, int cols)
* 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;