0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.0.0744: terminal window does not use a pty

Problem:    A terminal window uses pipes instead of a pty.
Solution:   Add pty support.
This commit is contained in:
Bram Moolenaar
2017-07-22 18:04:08 +02:00
parent 825680f5f4
commit 5a1feb8091
8 changed files with 102 additions and 64 deletions

View File

@@ -4096,6 +4096,32 @@ set_default_child_environment(void)
{
set_child_environment(Rows, Columns, "dumb");
}
#endif
#if defined(FEAT_GUI) || defined(FEAT_JOB_CHANNEL)
static void
open_pty(int *pty_master_fd, int *pty_slave_fd)
{
char *tty_name;
*pty_master_fd = OpenPTY(&tty_name); /* open pty */
if (*pty_master_fd >= 0)
{
/* Leaving out O_NOCTTY may lead to waitpid() always returning
* 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
* adding O_NOCTTY always works when defined. */
#ifdef O_NOCTTY
*pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
#else
*pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
#endif
if (*pty_slave_fd < 0)
{
close(*pty_master_fd);
*pty_master_fd = -1;
}
}
}
#endif
int
@@ -4206,7 +4232,6 @@ mch_call_shell(
int pty_master_fd = -1; /* for pty's */
# ifdef FEAT_GUI
int pty_slave_fd = -1;
char *tty_name;
# endif
int fd_toshell[2]; /* for pipes */
int fd_fromshell[2];
@@ -4269,25 +4294,7 @@ mch_call_shell(
* If the slave can't be opened, close the master pty.
*/
if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
{
pty_master_fd = OpenPTY(&tty_name); /* open pty */
if (pty_master_fd >= 0)
{
/* Leaving out O_NOCTTY may lead to waitpid() always returning
* 0 on Mac OS X 10.7 thereby causing freezes. Let's assume
* adding O_NOCTTY always works when defined. */
#ifdef O_NOCTTY
pty_slave_fd = open(tty_name, O_RDWR | O_NOCTTY | O_EXTRA, 0);
#else
pty_slave_fd = open(tty_name, O_RDWR | O_EXTRA, 0);
#endif
if (pty_slave_fd < 0)
{
close(pty_master_fd);
pty_master_fd = -1;
}
}
}
open_pty(&pty_master_fd, &pty_slave_fd);
/*
* If not opening a pty or it didn't work, try using pipes.
*/
@@ -5100,12 +5107,14 @@ error:
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
void
mch_start_job(char **argv, job_T *job, jobopt_T *options)
mch_job_start(char **argv, job_T *job, jobopt_T *options)
{
pid_t pid;
int fd_in[2]; /* for stdin */
int fd_out[2]; /* for stdout */
int fd_err[2]; /* for stderr */
int pty_master_fd = -1;
int pty_slave_fd = -1;
channel_T *channel = NULL;
int use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
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)
fd_err[0] = -1;
fd_err[1] = -1;
if (options->jo_pty)
open_pty(&pty_master_fd, &pty_slave_fd);
/* TODO: without the channel feature connect the child to /dev/null? */
/* Open pipes for stdin, stdout, stderr. */
if (use_file_for_in)
@@ -5141,7 +5153,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
goto failed;
}
}
else if (!use_null_for_in && pipe(fd_in) < 0)
else if (!use_null_for_in && pty_master_fd < 0 && pipe(fd_in) < 0)
goto failed;
if (use_file_for_out)
@@ -5155,7 +5167,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
goto failed;
}
}
else if (!use_null_for_out && pipe(fd_out) < 0)
else if (!use_null_for_out && pty_master_fd < 0 && pipe(fd_out) < 0)
goto failed;
if (use_file_for_err)
@@ -5169,7 +5181,8 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
goto failed;
}
}
else if (!use_out_for_err && !use_null_for_err && pipe(fd_err) < 0)
else if (!use_out_for_err && !use_null_for_err
&& pty_master_fd < 0 && pipe(fd_err) < 0)
goto failed;
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)
null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
/* set up stdin for the child */
close(0);
if (use_null_for_in && null_fd >= 0)
{
close(0);
ignored = dup(null_fd);
}
else if (fd_in[0] < 0)
ignored = dup(pty_slave_fd);
else
{
if (!use_file_for_in)
close(fd_in[1]);
close(0);
ignored = dup(fd_in[0]);
close(fd_in[0]);
}
/* set up stderr for the child */
close(2);
if (use_null_for_err && null_fd >= 0)
{
close(2);
ignored = dup(null_fd);
stderr_works = FALSE;
}
else if (use_out_for_err)
{
close(2);
ignored = dup(fd_out[1]);
}
else if (fd_err[1] < 0)
ignored = dup(pty_slave_fd);
else
{
if (!use_file_for_err)
close(fd_err[0]);
close(2);
ignored = dup(fd_err[1]);
close(fd_err[1]);
}
/* set up stdout for the child */
close(1);
if (use_null_for_out && null_fd >= 0)
{
close(1);
ignored = dup(null_fd);
}
else if (fd_out[1] < 0)
ignored = dup(pty_slave_fd);
else
{
if (!use_file_for_out)
close(fd_out[0]);
close(1);
ignored = dup(fd_out[1]);
if (fd_in[0] >= 0)
close(fd_in[0]);
if (fd_in[1] >= 0)
close(fd_in[1]);
if (fd_out[0] >= 0)
close(fd_out[0]);
if (fd_out[1] >= 0)
close(fd_out[1]);
if (fd_err[0] >= 0)
close(fd_err[0]);
if (fd_err[1] >= 0)
close(fd_err[1]);
if (pty_master_fd >= 0)
{
close(pty_master_fd); /* not used */
close(pty_slave_fd); /* duped above */
}
if (null_fd >= 0)
@@ -5296,7 +5308,9 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
job->jv_status = JOB_STARTED;
job->jv_channel = channel; /* ch_refcount was set above */
/* child stdin, stdout and stderr */
if (pty_master_fd >= 0)
close(pty_slave_fd); /* duped above */
/* close child stdin, stdout and stderr */
if (!use_file_for_in && fd_in[0] >= 0)
close(fd_in[0]);
if (!use_file_for_out && fd_out[1] >= 0)
@@ -5306,12 +5320,12 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options)
if (channel != NULL)
{
channel_set_pipes(channel,
use_file_for_in || use_null_for_in
? INVALID_FD : fd_in[1],
use_file_for_out || use_null_for_out
? INVALID_FD : fd_out[0],
use_out_for_err || use_file_for_err || use_null_for_err
? INVALID_FD : fd_err[0]);
use_file_for_in || use_null_for_in
? INVALID_FD : fd_in[1] < 0 ? pty_master_fd : fd_in[1],
use_file_for_out || use_null_for_out
? INVALID_FD : fd_out[0] < 0 ? pty_master_fd : fd_out[0],
use_out_for_err || use_file_for_err || use_null_for_err
? INVALID_FD : fd_err[0] < 0 ? pty_master_fd : fd_err[0]);
channel_set_job(channel, job, options);
}
@@ -5332,6 +5346,10 @@ failed:
close(fd_err[0]);
if (fd_err[1] >= 0)
close(fd_err[1]);
if (pty_master_fd >= 0)
close(pty_master_fd);
if (pty_slave_fd >= 0)
close(pty_slave_fd);
}
char *