@@ -4154,10 +4154,13 @@ wait4pid(pid_t child, waitstatus *status)
41544154 return wait_pid ;
41554155}
41564156
4157- #if defined(FEAT_JOB_CHANNEL ) || !defined(USE_SYSTEM ) || defined(PROTO )
4157+ #if defined(FEAT_JOB_CHANNEL ) \
4158+ || !defined(USE_SYSTEM ) \
4159+ || (defined(FEAT_GUI ) && defined(FEAT_TERMINAL )) \
4160+ || defined(PROTO )
41584161/*
41594162 * Parse "cmd" and put the white-separated parts in "argv".
4160- * "argv" is an allocated array with "argc" entries.
4163+ * "argv" is an allocated array with "argc" entries and room for 4 more .
41614164 * Returns FAIL when out of memory.
41624165 */
41634166 int
@@ -4359,8 +4362,121 @@ may_send_sigint(int c UNUSED, pid_t pid UNUSED, pid_t wpid UNUSED)
43594362# endif
43604363}
43614364
4362- int
4363- mch_call_shell (
4365+ #if !defined(USE_SYSTEM ) || (defined(FEAT_GUI ) && defined(FEAT_TERMINAL ))
4366+
4367+ static int
4368+ build_argv (
4369+ char_u * cmd ,
4370+ char * * * argvp ,
4371+ char_u * * sh_tofree ,
4372+ char_u * * shcf_tofree )
4373+ {
4374+ char * * argv = NULL ;
4375+ int argc ;
4376+
4377+ * sh_tofree = vim_strsave (p_sh );
4378+ if (* sh_tofree == NULL ) /* out of memory */
4379+ return FAIL ;
4380+
4381+ if (mch_parse_cmd (* sh_tofree , TRUE, & argv , & argc ) == FAIL )
4382+ return FAIL ;
4383+ * argvp = argv ;
4384+
4385+ if (cmd != NULL )
4386+ {
4387+ char_u * s ;
4388+ char_u * p ;
4389+
4390+ if (extra_shell_arg != NULL )
4391+ argv [argc ++ ] = (char * )extra_shell_arg ;
4392+
4393+ /* Break 'shellcmdflag' into white separated parts. This doesn't
4394+ * handle quoted strings, they are very unlikely to appear. */
4395+ * shcf_tofree = alloc ((unsigned )STRLEN (p_shcf ) + 1 );
4396+ if (* shcf_tofree == NULL ) /* out of memory */
4397+ return FAIL ;
4398+ s = * shcf_tofree ;
4399+ p = p_shcf ;
4400+ while (* p != NUL )
4401+ {
4402+ argv [argc ++ ] = (char * )s ;
4403+ while (* p && * p != ' ' && * p != TAB )
4404+ * s ++ = * p ++ ;
4405+ * s ++ = NUL ;
4406+ p = skipwhite (p );
4407+ }
4408+
4409+ argv [argc ++ ] = (char * )cmd ;
4410+ }
4411+ argv [argc ] = NULL ;
4412+ return OK ;
4413+ }
4414+ #endif
4415+
4416+ #if defined(FEAT_GUI ) && defined(FEAT_TERMINAL )
4417+ /*
4418+ * Use a terminal window to run a shell command in.
4419+ */
4420+ static int
4421+ mch_call_shell_terminal (
4422+ char_u * cmd ,
4423+ int options UNUSED ) /* SHELL_*, see vim.h */
4424+ {
4425+ jobopt_T opt ;
4426+ char * * argv = NULL ;
4427+ char_u * tofree1 = NULL ;
4428+ char_u * tofree2 = NULL ;
4429+ int retval = -1 ;
4430+ buf_T * buf ;
4431+ aco_save_T aco ;
4432+ oparg_T oa ; /* operator arguments */
4433+
4434+ if (build_argv (cmd , & argv , & tofree1 , & tofree2 ) == FAIL )
4435+ goto theend ;
4436+
4437+ init_job_options (& opt );
4438+ ch_log (NULL , "starting terminal for system command '%s'" , cmd );
4439+ buf = term_start (NULL , argv , & opt , TERM_START_SYSTEM );
4440+
4441+ /* Find a window to make "buf" curbuf. */
4442+ aucmd_prepbuf (& aco , buf );
4443+
4444+ clear_oparg (& oa );
4445+ while (term_use_loop ())
4446+ {
4447+ if (oa .op_type == OP_NOP && oa .regname == NUL && !VIsual_active )
4448+ {
4449+ /* If terminal_loop() returns OK we got a key that is handled
4450+ * in Normal model. We don't do redrawing anyway. */
4451+ if (terminal_loop (TRUE) == OK )
4452+ normal_cmd (& oa , TRUE);
4453+ }
4454+ else
4455+ normal_cmd (& oa , TRUE);
4456+ }
4457+ retval = 0 ;
4458+ ch_log (NULL , "system command finished" );
4459+
4460+ /* restore curwin/curbuf and a few other things */
4461+ aucmd_restbuf (& aco );
4462+
4463+ wait_return (TRUE);
4464+ do_buffer (DOBUF_WIPE , DOBUF_FIRST , FORWARD , buf -> b_fnum , TRUE);
4465+
4466+ theend :
4467+ vim_free (argv );
4468+ vim_free (tofree1 );
4469+ vim_free (tofree2 );
4470+ return retval ;
4471+ }
4472+ #endif
4473+
4474+ #ifdef USE_SYSTEM
4475+ /*
4476+ * Use system() to start the shell: simple but slow.
4477+ */
4478+ static int
4479+ mch_call_shell_system (
43644480 char_u * cmd ,
43654481 int options ) /* SHELL_*, see vim.h */
43664482{
@@ -4369,7 +4485,6 @@ mch_call_shell(
43694485 char * ofn = NULL ;
43704486#endif
43714487 int tmode = cur_tmode ;
4372- #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
43734488 char_u * newcmd ; /* only needed for unix */
43744489 int x ;
43754490
@@ -4443,14 +4558,23 @@ mch_call_shell(
44434558 restore_clipboard ();
44444559# endif
44454560 return x ;
4561+ }
44464562
4447- #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
4563+ #else /* USE_SYSTEM */
44484564
44494565# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
44504566 127, some shells use that already */
44514567# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
44524568
4453- char_u * newcmd ;
4569+ /*
4570+ * Don't use system(), use fork()/exec().
4571+ */
4572+ static int
4573+ mch_call_shell_fork (
4574+ char_u * cmd ,
4575+ int options ) /* SHELL_*, see vim.h */
4576+ {
4577+ int tmode = cur_tmode ;
44544578 pid_t pid ;
44554579 pid_t wpid = 0 ;
44564580 pid_t wait_pid = 0 ;
@@ -4461,8 +4585,8 @@ mch_call_shell(
44614585# endif
44624586 int retval = -1 ;
44634587 char * * argv = NULL ;
4464- int argc ;
4465- char_u * p_shcf_copy = NULL ;
4588+ char_u * tofree1 = NULL ;
4589+ char_u * tofree2 = NULL ;
44664590 int i ;
44674591 char_u * p ;
44684592 int pty_master_fd = -1 ; /* for pty's */
@@ -4474,44 +4598,13 @@ mch_call_shell(
44744598 int pipe_error = FALSE;
44754599 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
44764600
4477- newcmd = vim_strsave (p_sh );
4478- if (newcmd == NULL ) /* out of memory */
4479- goto error ;
4480-
44814601 out_flush ();
44824602 if (options & SHELL_COOKED )
44834603 settmode (TMODE_COOK ); /* set to normal mode */
44844604
4485- if (mch_parse_cmd ( newcmd , TRUE , & argv , & argc ) == FAIL )
4605+ if (build_argv ( cmd , & argv , & tofree1 , & tofree2 ) == FAIL )
44864606 goto error ;
44874607
4488- if (cmd != NULL )
4489- {
4490- char_u * s ;
4491-
4492- if (extra_shell_arg != NULL )
4493- argv [argc ++ ] = (char * )extra_shell_arg ;
4494-
4495- /* Break 'shellcmdflag' into white separated parts. This doesn't
4496- * handle quoted strings, they are very unlikely to appear. */
4497- p_shcf_copy = alloc ((unsigned )STRLEN (p_shcf ) + 1 );
4498- if (p_shcf_copy == NULL ) /* out of memory */
4499- goto error ;
4500- s = p_shcf_copy ;
4501- p = p_shcf ;
4502- while (* p != NUL )
4503- {
4504- argv [argc ++ ] = (char * )s ;
4505- while (* p && * p != ' ' && * p != TAB )
4506- * s ++ = * p ++ ;
4507- * s ++ = NUL ;
4508- p = skipwhite (p );
4509- }
4510-
4511- argv [argc ++ ] = (char * )cmd ;
4512- }
4513- argv [argc ] = NULL ;
4514-
45154608 /*
45164609 * For the GUI, when writing the output into the buffer and when reading
45174610 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
@@ -5319,8 +5412,6 @@ mch_call_shell(
53195412 MSG_PUTS (_ ("\nCommand terminated\n" ));
53205413 }
53215414 }
5322- vim_free (argv );
5323- vim_free (p_shcf_copy );
53245415
53255416error :
53265417 if (!did_settmode )
@@ -5329,11 +5420,28 @@ mch_call_shell(
53295420# ifdef FEAT_TITLE
53305421 resettitle ();
53315422# endif
5332- vim_free (newcmd );
5423+ vim_free (argv );
5424+ vim_free (tofree1 );
5425+ vim_free (tofree2 );
53335426
53345427 return retval ;
5335-
5428+ }
53365429#endif /* USE_SYSTEM */
5430+
5431+ int
5432+ mch_call_shell (
5433+ char_u * cmd ,
5434+ int options ) /* SHELL_*, see vim.h */
5435+ {
5436+ #if defined(FEAT_GUI ) && defined(FEAT_TERMINAL )
5437+ if (gui .in_use && vim_strchr (p_go , GO_TERMINAL ) != NULL )
5438+ return mch_call_shell_terminal (cmd , options );
5439+ #endif
5440+ #ifdef USE_SYSTEM
5441+ return mch_call_shell_system (cmd , options );
5442+ #else
5443+ return mch_call_shell_fork (cmd , options );
5444+ #endif
53375445}
53385446
53395447#if defined(FEAT_JOB_CHANNEL ) || defined(PROTO )
0 commit comments