@@ -4096,6 +4096,32 @@ set_default_child_environment(void)
40964096{
40974097 set_child_environment (Rows , Columns , "dumb" );
40984098}
4099+ #endif
4100+
4101+ #if defined(FEAT_GUI ) || defined(FEAT_JOB_CHANNEL )
4102+ static void
4103+ open_pty (int * pty_master_fd , int * pty_slave_fd )
4104+ {
4105+ char * tty_name ;
4106+
4107+ * pty_master_fd = OpenPTY (& tty_name ); /* open pty */
4108+ if (* pty_master_fd >= 0 )
4109+ {
4110+ /* Leaving out O_NOCTTY may lead to waitpid() always returning
4111+ * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
4112+ * adding O_NOCTTY always works when defined. */
4113+ #ifdef O_NOCTTY
4114+ * pty_slave_fd = open (tty_name , O_RDWR | O_NOCTTY | O_EXTRA , 0 );
4115+ #else
4116+ * pty_slave_fd = open (tty_name , O_RDWR | O_EXTRA , 0 );
4117+ #endif
4118+ if (* pty_slave_fd < 0 )
4119+ {
4120+ close (* pty_master_fd );
4121+ * pty_master_fd = -1 ;
4122+ }
4123+ }
4124+ }
40994125#endif
41004126
41014127 int
@@ -4206,7 +4232,6 @@ mch_call_shell(
42064232 int pty_master_fd = -1 ; /* for pty's */
42074233# ifdef FEAT_GUI
42084234 int pty_slave_fd = -1 ;
4209- char * tty_name ;
42104235# endif
42114236 int fd_toshell [2 ]; /* for pipes */
42124237 int fd_fromshell [2 ];
@@ -4269,25 +4294,7 @@ mch_call_shell(
42694294 * If the slave can't be opened, close the master pty.
42704295 */
42714296 if (p_guipty && !(options & (SHELL_READ |SHELL_WRITE )))
4272- {
4273- pty_master_fd = OpenPTY (& tty_name ); /* open pty */
4274- if (pty_master_fd >= 0 )
4275- {
4276- /* Leaving out O_NOCTTY may lead to waitpid() always returning
4277- * 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
4278- * adding O_NOCTTY always works when defined. */
4279- #ifdef O_NOCTTY
4280- pty_slave_fd = open (tty_name , O_RDWR | O_NOCTTY | O_EXTRA , 0 );
4281- #else
4282- pty_slave_fd = open (tty_name , O_RDWR | O_EXTRA , 0 );
4283- #endif
4284- if (pty_slave_fd < 0 )
4285- {
4286- close (pty_master_fd );
4287- pty_master_fd = -1 ;
4288- }
4289- }
4290- }
4297+ open_pty (& pty_master_fd , & pty_slave_fd );
42914298 /*
42924299 * If not opening a pty or it didn't work, try using pipes.
42934300 */
@@ -5100,12 +5107,14 @@ mch_call_shell(
51005107
51015108#if defined(FEAT_JOB_CHANNEL ) || defined(PROTO )
51025109 void
5103- mch_start_job (char * * argv , job_T * job , jobopt_T * options )
5110+ mch_job_start (char * * argv , job_T * job , jobopt_T * options )
51045111{
51055112 pid_t pid ;
51065113 int fd_in [2 ]; /* for stdin */
51075114 int fd_out [2 ]; /* for stdout */
51085115 int fd_err [2 ]; /* for stderr */
5116+ int pty_master_fd = -1 ;
5117+ int pty_slave_fd = -1 ;
51095118 channel_T * channel = NULL ;
51105119 int use_null_for_in = options -> jo_io [PART_IN ] == JIO_NULL ;
51115120 int use_null_for_out = options -> jo_io [PART_OUT ] == JIO_NULL ;
@@ -5128,6 +5137,9 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
51285137 fd_err [0 ] = -1 ;
51295138 fd_err [1 ] = -1 ;
51305139
5140+ if (options -> jo_pty )
5141+ open_pty (& pty_master_fd , & pty_slave_fd );
5142+
51315143 /* TODO: without the channel feature connect the child to /dev/null? */
51325144 /* Open pipes for stdin, stdout, stderr. */
51335145 if (use_file_for_in )
@@ -5141,7 +5153,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
51415153 goto failed ;
51425154 }
51435155 }
5144- else if (!use_null_for_in && pipe (fd_in ) < 0 )
5156+ else if (!use_null_for_in && pty_master_fd < 0 && pipe (fd_in ) < 0 )
51455157 goto failed ;
51465158
51475159 if (use_file_for_out )
@@ -5155,7 +5167,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
51555167 goto failed ;
51565168 }
51575169 }
5158- else if (!use_null_for_out && pipe (fd_out ) < 0 )
5170+ else if (!use_null_for_out && pty_master_fd < 0 && pipe (fd_out ) < 0 )
51595171 goto failed ;
51605172
51615173 if (use_file_for_err )
@@ -5169,7 +5181,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
51695181 goto failed ;
51705182 }
51715183 }
5172- else if (!use_out_for_err && !use_null_for_err && pipe (fd_err ) < 0 )
5184+ else if (!use_out_for_err && !use_null_for_err
5185+ && pty_master_fd < 0 && pipe (fd_err ) < 0 )
51735186 goto failed ;
51745187
51755188 if (!use_null_for_in || !use_null_for_out || !use_null_for_err )
@@ -5224,54 +5237,53 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
52245237 null_fd = open ("/dev/null" , O_RDWR | O_EXTRA , 0 );
52255238
52265239 /* set up stdin for the child */
5240+ close (0 );
52275241 if (use_null_for_in && null_fd >= 0 )
5228- {
5229- close (0 );
52305242 ignored = dup (null_fd );
5231- }
5243+ else if (fd_in [0 ] < 0 )
5244+ ignored = dup (pty_slave_fd );
52325245 else
5233- {
5234- if (!use_file_for_in )
5235- close (fd_in [1 ]);
5236- close (0 );
52375246 ignored = dup (fd_in [0 ]);
5238- close (fd_in [0 ]);
5239- }
52405247
52415248 /* set up stderr for the child */
5249+ close (2 );
52425250 if (use_null_for_err && null_fd >= 0 )
52435251 {
5244- close (2 );
52455252 ignored = dup (null_fd );
52465253 stderr_works = FALSE;
52475254 }
52485255 else if (use_out_for_err )
5249- {
5250- close (2 );
52515256 ignored = dup (fd_out [1 ]);
5252- }
5257+ else if (fd_err [1 ] < 0 )
5258+ ignored = dup (pty_slave_fd );
52535259 else
5254- {
5255- if (!use_file_for_err )
5256- close (fd_err [0 ]);
5257- close (2 );
52585260 ignored = dup (fd_err [1 ]);
5259- close (fd_err [1 ]);
5260- }
52615261
52625262 /* set up stdout for the child */
5263+ close (1 );
52635264 if (use_null_for_out && null_fd >= 0 )
5264- {
5265- close (1 );
52665265 ignored = dup (null_fd );
5267- }
5266+ else if (fd_out [1 ] < 0 )
5267+ ignored = dup (pty_slave_fd );
52685268 else
5269- {
5270- if (!use_file_for_out )
5271- close (fd_out [0 ]);
5272- close (1 );
52735269 ignored = dup (fd_out [1 ]);
5270+
5271+ if (fd_in [0 ] >= 0 )
5272+ close (fd_in [0 ]);
5273+ if (fd_in [1 ] >= 0 )
5274+ close (fd_in [1 ]);
5275+ if (fd_out [0 ] >= 0 )
5276+ close (fd_out [0 ]);
5277+ if (fd_out [1 ] >= 0 )
52745278 close (fd_out [1 ]);
5279+ if (fd_err [0 ] >= 0 )
5280+ close (fd_err [0 ]);
5281+ if (fd_err [1 ] >= 0 )
5282+ close (fd_err [1 ]);
5283+ if (pty_master_fd >= 0 )
5284+ {
5285+ close (pty_master_fd ); /* not used */
5286+ close (pty_slave_fd ); /* duped above */
52755287 }
52765288
52775289 if (null_fd >= 0 )
@@ -5296,7 +5308,9 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
52965308 job -> jv_status = JOB_STARTED ;
52975309 job -> jv_channel = channel ; /* ch_refcount was set above */
52985310
5299- /* child stdin, stdout and stderr */
5311+ if (pty_master_fd >= 0 )
5312+ close (pty_slave_fd ); /* duped above */
5313+ /* close child stdin, stdout and stderr */
53005314 if (!use_file_for_in && fd_in [0 ] >= 0 )
53015315 close (fd_in [0 ]);
53025316 if (!use_file_for_out && fd_out [1 ] >= 0 )
@@ -5306,12 +5320,12 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
53065320 if (channel != NULL )
53075321 {
53085322 channel_set_pipes (channel ,
5309- use_file_for_in || use_null_for_in
5310- ? INVALID_FD : fd_in [1 ],
5311- use_file_for_out || use_null_for_out
5312- ? INVALID_FD : fd_out [0 ],
5313- use_out_for_err || use_file_for_err || use_null_for_err
5314- ? INVALID_FD : fd_err [0 ]);
5323+ use_file_for_in || use_null_for_in
5324+ ? INVALID_FD : fd_in [ 1 ] < 0 ? pty_master_fd : fd_in [1 ],
5325+ use_file_for_out || use_null_for_out
5326+ ? INVALID_FD : fd_out [ 0 ] < 0 ? pty_master_fd : fd_out [0 ],
5327+ use_out_for_err || use_file_for_err || use_null_for_err
5328+ ? INVALID_FD : fd_err [ 0 ] < 0 ? pty_master_fd : fd_err [0 ]);
53155329 channel_set_job (channel , job , options );
53165330 }
53175331
@@ -5332,6 +5346,10 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
53325346 close (fd_err [0 ]);
53335347 if (fd_err [1 ] >= 0 )
53345348 close (fd_err [1 ]);
5349+ if (pty_master_fd >= 0 )
5350+ close (pty_master_fd );
5351+ if (pty_slave_fd >= 0 )
5352+ close (pty_slave_fd );
53355353}
53365354
53375355 char *
0 commit comments