@@ -4160,10 +4160,13 @@ wait4pid(pid_t child, waitstatus *status)
41604160 return wait_pid ;
41614161}
41624162
4163- #if defined(FEAT_JOB_CHANNEL ) || !defined(USE_SYSTEM ) || defined(PROTO )
4163+ #if defined(FEAT_JOB_CHANNEL ) \
4164+ || !defined(USE_SYSTEM ) \
4165+ || (defined(FEAT_GUI ) && defined(FEAT_TERMINAL )) \
4166+ || defined(PROTO )
41644167/*
41654168 * Parse "cmd" and put the white-separated parts in "argv".
4166- * "argv" is an allocated array with "argc" entries.
4169+ * "argv" is an allocated array with "argc" entries and room for 4 more .
41674170 * Returns FAIL when out of memory.
41684171 */
41694172 int
@@ -4365,8 +4368,121 @@ may_send_sigint(int c UNUSED, pid_t pid UNUSED, pid_t wpid UNUSED)
43654368# endif
43664369}
43674370
4368- int
4369- mch_call_shell (
4371+ #if !defined(USE_SYSTEM ) || (defined(FEAT_GUI ) && defined(FEAT_TERMINAL ))
4372+
4373+ static int
4374+ build_argv (
4375+ char_u * cmd ,
4376+ char * * * argvp ,
4377+ char_u * * sh_tofree ,
4378+ char_u * * shcf_tofree )
4379+ {
4380+ char * * argv = NULL ;
4381+ int argc ;
4382+
4383+ * sh_tofree = vim_strsave (p_sh );
4384+ if (* sh_tofree == NULL ) /* out of memory */
4385+ return FAIL ;
4386+
4387+ if (mch_parse_cmd (* sh_tofree , TRUE, & argv , & argc ) == FAIL )
4388+ return FAIL ;
4389+ * argvp = argv ;
4390+
4391+ if (cmd != NULL )
4392+ {
4393+ char_u * s ;
4394+ char_u * p ;
4395+
4396+ if (extra_shell_arg != NULL )
4397+ argv [argc ++ ] = (char * )extra_shell_arg ;
4398+
4399+ /* Break 'shellcmdflag' into white separated parts. This doesn't
4400+ * handle quoted strings, they are very unlikely to appear. */
4401+ * shcf_tofree = alloc ((unsigned )STRLEN (p_shcf ) + 1 );
4402+ if (* shcf_tofree == NULL ) /* out of memory */
4403+ return FAIL ;
4404+ s = * shcf_tofree ;
4405+ p = p_shcf ;
4406+ while (* p != NUL )
4407+ {
4408+ argv [argc ++ ] = (char * )s ;
4409+ while (* p && * p != ' ' && * p != TAB )
4410+ * s ++ = * p ++ ;
4411+ * s ++ = NUL ;
4412+ p = skipwhite (p );
4413+ }
4414+
4415+ argv [argc ++ ] = (char * )cmd ;
4416+ }
4417+ argv [argc ] = NULL ;
4418+ return OK ;
4419+ }
4420+ #endif
4421+
4422+ #if defined(FEAT_GUI ) && defined(FEAT_TERMINAL )
4423+ /*
4424+ * Use a terminal window to run a shell command in.
4425+ */
4426+ static int
4427+ mch_call_shell_terminal (
4428+ char_u * cmd ,
4429+ int options UNUSED ) /* SHELL_*, see vim.h */
4430+ {
4431+ jobopt_T opt ;
4432+ char * * argv = NULL ;
4433+ char_u * tofree1 = NULL ;
4434+ char_u * tofree2 = NULL ;
4435+ int retval = -1 ;
4436+ buf_T * buf ;
4437+ aco_save_T aco ;
4438+ oparg_T oa ; /* operator arguments */
4439+
4440+ if (build_argv (cmd , & argv , & tofree1 , & tofree2 ) == FAIL )
4441+ goto theend ;
4442+
4443+ init_job_options (& opt );
4444+ ch_log (NULL , "starting terminal for system command '%s'" , cmd );
4445+ buf = term_start (NULL , argv , & opt , TERM_START_SYSTEM );
4446+
4447+ /* Find a window to make "buf" curbuf. */
4448+ aucmd_prepbuf (& aco , buf );
4449+
4450+ clear_oparg (& oa );
4451+ while (term_use_loop ())
4452+ {
4453+ if (oa .op_type == OP_NOP && oa .regname == NUL && !VIsual_active )
4454+ {
4455+ /* If terminal_loop() returns OK we got a key that is handled
4456+ * in Normal model. We don't do redrawing anyway. */
4457+ if (terminal_loop (TRUE) == OK )
4458+ normal_cmd (& oa , TRUE);
4459+ }
4460+ else
4461+ normal_cmd (& oa , TRUE);
4462+ }
4463+ retval = 0 ;
4464+ ch_log (NULL , "system command finished" );
4465+
4466+ /* restore curwin/curbuf and a few other things */
4467+ aucmd_restbuf (& aco );
4468+
4469+ wait_return (TRUE);
4470+ do_buffer (DOBUF_WIPE , DOBUF_FIRST , FORWARD , buf -> b_fnum , TRUE);
4471+
4472+ theend :
4473+ vim_free (argv );
4474+ vim_free (tofree1 );
4475+ vim_free (tofree2 );
4476+ return retval ;
4477+ }
4478+ #endif
4479+
4480+ #ifdef USE_SYSTEM
4481+ /*
4482+ * Use system() to start the shell: simple but slow.
4483+ */
4484+ static int
4485+ mch_call_shell_system (
43704486 char_u * cmd ,
43714487 int options ) /* SHELL_*, see vim.h */
43724488{
@@ -4375,7 +4491,6 @@ mch_call_shell(
43754491 char * ofn = NULL ;
43764492#endif
43774493 int tmode = cur_tmode ;
4378- #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
43794494 char_u * newcmd ; /* only needed for unix */
43804495 int x ;
43814496
@@ -4455,14 +4570,23 @@ mch_call_shell(
44554570 restore_clipboard ();
44564571# endif
44574572 return x ;
4573+ }
44584574
4459- #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
4575+ #else /* USE_SYSTEM */
44604576
44614577# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
44624578 127, some shells use that already */
44634579# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
44644580
4465- char_u * newcmd ;
4581+ /*
4582+ * Don't use system(), use fork()/exec().
4583+ */
4584+ static int
4585+ mch_call_shell_fork (
4586+ char_u * cmd ,
4587+ int options ) /* SHELL_*, see vim.h */
4588+ {
4589+ int tmode = cur_tmode ;
44664590 pid_t pid ;
44674591 pid_t wpid = 0 ;
44684592 pid_t wait_pid = 0 ;
@@ -4473,8 +4597,8 @@ mch_call_shell(
44734597# endif
44744598 int retval = -1 ;
44754599 char * * argv = NULL ;
4476- int argc ;
4477- char_u * p_shcf_copy = NULL ;
4600+ char_u * tofree1 = NULL ;
4601+ char_u * tofree2 = NULL ;
44784602 int i ;
44794603 char_u * p ;
44804604 int pty_master_fd = -1 ; /* for pty's */
@@ -4486,10 +4610,6 @@ mch_call_shell(
44864610 int pipe_error = FALSE;
44874611 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
44884612
4489- newcmd = vim_strsave (p_sh );
4490- if (newcmd == NULL ) /* out of memory */
4491- goto error ;
4492-
44934613 out_flush ();
44944614#ifdef FEAT_GUI_MACVIM
44954615 /* It is conceivable that the shell command will take a long time to finish
@@ -4500,36 +4620,9 @@ mch_call_shell(
45004620 if (options & SHELL_COOKED )
45014621 settmode (TMODE_COOK ); /* set to normal mode */
45024622
4503- if (mch_parse_cmd ( newcmd , TRUE , & argv , & argc ) == FAIL )
4623+ if (build_argv ( cmd , & argv , & tofree1 , & tofree2 ) == FAIL )
45044624 goto error ;
45054625
4506- if (cmd != NULL )
4507- {
4508- char_u * s ;
4509-
4510- if (extra_shell_arg != NULL )
4511- argv [argc ++ ] = (char * )extra_shell_arg ;
4512-
4513- /* Break 'shellcmdflag' into white separated parts. This doesn't
4514- * handle quoted strings, they are very unlikely to appear. */
4515- p_shcf_copy = alloc ((unsigned )STRLEN (p_shcf ) + 1 );
4516- if (p_shcf_copy == NULL ) /* out of memory */
4517- goto error ;
4518- s = p_shcf_copy ;
4519- p = p_shcf ;
4520- while (* p != NUL )
4521- {
4522- argv [argc ++ ] = (char * )s ;
4523- while (* p && * p != ' ' && * p != TAB )
4524- * s ++ = * p ++ ;
4525- * s ++ = NUL ;
4526- p = skipwhite (p );
4527- }
4528-
4529- argv [argc ++ ] = (char * )cmd ;
4530- }
4531- argv [argc ] = NULL ;
4532-
45334626 /*
45344627 * For the GUI, when writing the output into the buffer and when reading
45354628 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
@@ -5341,8 +5434,6 @@ mch_call_shell(
53415434 MSG_PUTS (_ ("\nCommand terminated\n" ));
53425435 }
53435436 }
5344- vim_free (argv );
5345- vim_free (p_shcf_copy );
53465437
53475438error :
53485439 if (!did_settmode )
@@ -5351,11 +5442,28 @@ mch_call_shell(
53515442# ifdef FEAT_TITLE
53525443 resettitle ();
53535444# endif
5354- vim_free (newcmd );
5445+ vim_free (argv );
5446+ vim_free (tofree1 );
5447+ vim_free (tofree2 );
53555448
53565449 return retval ;
5357-
5450+ }
53585451#endif /* USE_SYSTEM */
5452+
5453+ int
5454+ mch_call_shell (
5455+ char_u * cmd ,
5456+ int options ) /* SHELL_*, see vim.h */
5457+ {
5458+ #if defined(FEAT_GUI ) && defined(FEAT_TERMINAL )
5459+ if (gui .in_use && vim_strchr (p_go , GO_TERMINAL ) != NULL )
5460+ return mch_call_shell_terminal (cmd , options );
5461+ #endif
5462+ #ifdef USE_SYSTEM
5463+ return mch_call_shell_system (cmd , options );
5464+ #else
5465+ return mch_call_shell_fork (cmd , options );
5466+ #endif
53595467}
53605468
53615469#if defined(FEAT_JOB_CHANNEL ) || defined(PROTO )
0 commit comments