summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_tty.cc
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2015-04-22 13:22:59 +0200
committerCorinna Vinschen <corinna@vinschen.de>2015-04-23 22:04:24 +0200
commitc846bca9921f577956499aa0d8463c04e5694d46 (patch)
tree9c1fdbff8518fe49fb34c04b579f98ead8edd76d /winsup/cygwin/fhandler_tty.cc
parent6d099d5bae856af2b92ab3f7812632f0ea8ae7ea (diff)
downloadcygnal-c846bca9921f577956499aa0d8463c04e5694d46.tar.gz
cygnal-c846bca9921f577956499aa0d8463c04e5694d46.tar.bz2
cygnal-c846bca9921f577956499aa0d8463c04e5694d46.zip
Fix OPOST for non-Cygwin pty slaves
* fhandler.h (class fhandler_base): Add virtual function get_io_handle_cyg() to get handle from which OPOST-processed output is read on PTY master. (class fhandler_pty_slave): Add variable output_handle_cyg to store a handle to which OPOST-processed output is written. Add two functions, i.e., set_output_handle_cyg() and get_output_handle_cyg(), regarding variable output_handle_cyg. Now, output_handle is used only by native windows program. The data before OPOST-processing is written to output_handle and OPOST-processing is applied in the master-side. For a cygwin process, OPOST-processing is applied in the slave-side, and the data after OPOST-processing is written to output_handle_cyg. (class fhandler_pty_master): Add two variables, i.e., io_handle_cyg and to_master_cyg, to store handles of a pipe through which OPOST-processed output passes. Add pty_master_fwd_thread and function pty_master_fwd_thread() for a thread which applies OPOST-processing and forwards data from io_handle to to_master_cyg. Add function get_io_handle_cyg() regarding variable io_handle_cyg. Now, the pipe between io_handle and to_master are used only by native windows program for applying OPOST-processing in the master-side. For a cygwin process, the pipe between io_handle_cyg and to_master_cyg is used for passing through the data which is applied OPOST-processing in the slave-side. * fhandler_tty.cc (struct pipe_reply): Add member to_master_cyg. (fhandler_pty_master::process_slave_output): Read slave output from io_handle_cyg rather than io_handle. (fhandler_pty_slave::fhandler_pty_salve): Initialize output_handle_cyg. (fhandler_pty_slave::open): Set output_handle_cyg by duplicating handle to_master_cyg on PTY master. (fhandler_pty_slave::close): Close handle output_handle_cyg. (fhandler_pty_slave::write): Write data to output_handle_cyg rather than output_handle. (fhandler_pty_slave::fch_close_handles): Close handle output_handle_cyg. (fhandler_pty_master::fhandler_pty_master): Initialize io_handle_cyg, to_master_cyg and master_fwd_thread. (fhandler_pty_master::cleanup): Clean up to_master_cyg as well. (fhandler_pty_master::close): Print to_master_cyg as well in debug message. Terminate master forwarding thread. Close handles to_master_cyg and io_handle_cyg. (fhandler_pty_master::ioctl): Use io_handle_cyg rather than to_master. (fhandler_pty_master::pty_master_thread): Add code for duplicating handle to_master_cyg. (fhandler_pty_master::pty_master_fwd_thread): New function for a thread to forward OPOST-processed data from io_handle to to_master_cyg. This thread applies OPOST-processing to the output of native windows program. (::pty_master_fwd_thread): Ditto. (fhandler_pty_master::setup): Create a new pipe to pass thruegh OPOST- processed output. Create new thread to forward data from io_handle to to_master_cyg. Set handle to_master_cyg to tty. Print io_handle_cyg as well in debug message. Close handles io_handle_cyg and to_master_cyg in case of error. (fhandler_pty_master::fixup_after_fork): Set handle to_master_cyg to tty. Copy handle to_master_cyg from arch->to_master_cyg. (fhandler_pty_master::fixup_after_exec): Clean up to_master_cyg. * select.cc: Check handle returned by get_io_handle_cyg() rather than get_handle(). * tty.h (class tty): Add variable _to_master_cyg to store a handle to which OPOST-processed data is written. Add two functions, to_master_cyg() and set_to_master_cyg(), regarding _to_master_cyg. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/fhandler_tty.cc')
-rw-r--r--winsup/cygwin/fhandler_tty.cc121
1 files changed, 104 insertions, 17 deletions
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index daa24ebcc..d3fbcee86 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -42,6 +42,7 @@ struct pipe_request {
struct pipe_reply {
HANDLE from_master;
HANDLE to_master;
+ HANDLE to_master_cyg;
DWORD error;
};
@@ -236,7 +237,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
/* Check echo pipe first. */
if (::bytes_available (echo_cnt, echo_r) && echo_cnt > 0)
break;
- if (!bytes_available (n))
+ if (!::bytes_available (n, get_io_handle_cyg ()))
goto err;
if (n)
break;
@@ -297,7 +298,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on
goto err;
}
}
- else if (!ReadFile (get_handle (), outbuf, rlen, &n, NULL))
+ else if (!ReadFile (get_io_handle_cyg (), outbuf, rlen, &n, NULL))
{
termios_printf ("ReadFile failed, %E");
goto err;
@@ -332,7 +333,7 @@ out:
/* pty slave stuff */
fhandler_pty_slave::fhandler_pty_slave (int unit)
- : fhandler_pty_common (), inuse (NULL)
+ : fhandler_pty_common (), inuse (NULL), output_handle_cyg (NULL)
{
if (unit >= 0)
dev ().parse (DEV_PTYS_MAJOR, unit);
@@ -341,11 +342,11 @@ fhandler_pty_slave::fhandler_pty_slave (int unit)
int
fhandler_pty_slave::open (int flags, mode_t)
{
- HANDLE pty_owner, from_master_local, to_master_local;
+ HANDLE pty_owner, from_master_local, to_master_local, to_master_cyg_local;
HANDLE *handles[] =
{
&from_master_local, &input_available_event, &input_mutex, &inuse,
- &output_mutex, &to_master_local, &pty_owner,
+ &output_mutex, &to_master_local, &pty_owner, &to_master_cyg_local,
NULL
};
@@ -397,7 +398,8 @@ fhandler_pty_slave::open (int flags, mode_t)
release_output_mutex ();
}
- if (!get_ttyp ()->from_master () || !get_ttyp ()->to_master ())
+ if (!get_ttyp ()->from_master () ||
+ !get_ttyp ()->to_master () || !get_ttyp ()->to_master_cyg ())
{
errmsg = "pty handles have been closed";
set_errno (EACCES);
@@ -448,6 +450,13 @@ fhandler_pty_slave::open (int flags, mode_t)
errmsg = "can't duplicate output, %E";
goto err;
}
+ if (!DuplicateHandle (pty_owner, get_ttyp ()->to_master_cyg (),
+ GetCurrentProcess (), &to_master_cyg_local, 0, TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ errmsg = "can't duplicate output for cygwin, %E";
+ goto err;
+ }
if (pty_owner != GetCurrentProcess ())
CloseHandle (pty_owner);
}
@@ -468,7 +477,8 @@ fhandler_pty_slave::open (int flags, mode_t)
}
from_master_local = repl.from_master;
to_master_local = repl.to_master;
- if (!from_master_local || !to_master_local)
+ to_master_cyg_local = repl.to_master_cyg;
+ if (!from_master_local || !to_master_local || !to_master_cyg_local)
{
SetLastError (repl.error);
errmsg = "error duplicating pipes, %E";
@@ -477,14 +487,18 @@ fhandler_pty_slave::open (int flags, mode_t)
}
VerifyHandle (from_master_local);
VerifyHandle (to_master_local);
+ VerifyHandle (to_master_cyg_local);
termios_printf ("duplicated from_master %p->%p from pty_owner",
get_ttyp ()->from_master (), from_master_local);
termios_printf ("duplicated to_master %p->%p from pty_owner",
get_ttyp ()->to_master (), to_master_local);
+ termios_printf ("duplicated to_master_cyg %p->%p from pty_owner",
+ get_ttyp ()->to_master_cyg (), to_master_cyg_local);
set_io_handle (from_master_local);
set_output_handle (to_master_local);
+ set_output_handle_cyg (to_master_cyg_local);
fhandler_console::need_invisible ();
set_open_status ();
@@ -533,6 +547,9 @@ fhandler_pty_slave::close ()
termios_printf ("CloseHandle (inuse), %E");
if (!ForceCloseHandle (input_available_event))
termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
+ if (!ForceCloseHandle (get_output_handle_cyg ()))
+ termios_printf ("CloseHandle (get_output_handle_cyg ()<%p>), %E",
+ get_output_handle_cyg ());
if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ()))
fhandler_console::free_console (); /* assumes that we are the last pty closer */
return fhandler_pty_common::close ();
@@ -591,7 +608,7 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
push_process_state process_state (PID_TTYOU);
- if (!process_opost_output (get_output_handle (), ptr, towrite, false))
+ if (!process_opost_output (get_output_handle_cyg (), ptr, towrite, false))
{
DWORD err = GetLastError ();
termios_printf ("WriteFile failed, %E");
@@ -1069,6 +1086,7 @@ fhandler_pty_slave::fch_close_handles ()
{
close_maybe (get_io_handle ());
close_maybe (get_output_handle ());
+ close_maybe (get_output_handle_cyg ());
close_maybe (input_available_event);
close_maybe (output_mutex);
close_maybe (input_mutex);
@@ -1142,7 +1160,8 @@ errout:
fhandler_pty_master::fhandler_pty_master (int unit)
: fhandler_pty_common (), pktmode (0), master_ctl (NULL),
master_thread (NULL), from_master (NULL), to_master (NULL),
- echo_r (NULL), echo_w (NULL), dwProcessId (0)
+ echo_r (NULL), echo_w (NULL), dwProcessId (0),
+ io_handle_cyg (NULL), to_master_cyg (NULL), master_fwd_thread (NULL)
{
if (unit >= 0)
dev ().parse (DEV_PTYM_MAJOR, unit);
@@ -1200,15 +1219,15 @@ fhandler_pty_master::cleanup ()
{
report_tty_counts (this, "closing master", "");
if (archetype)
- from_master = to_master = NULL;
+ from_master = to_master = to_master_cyg = NULL;
fhandler_base::cleanup ();
}
int
fhandler_pty_master::close ()
{
- termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%u)",
- from_master, to_master, dwProcessId);
+ termios_printf ("closing from_master(%p)/to_master(%p)/to_master_cyg(%p) since we own them(%u)",
+ from_master, to_master, to_master_cyg, dwProcessId);
if (cygwin_finished_initializing)
{
if (master_ctl && get_ttyp ()->master_pid == myself->pid)
@@ -1231,6 +1250,7 @@ fhandler_pty_master::close ()
master_ctl = NULL;
}
release_output_mutex ();
+ master_fwd_thread->terminate_thread ();
}
}
@@ -1247,6 +1267,11 @@ fhandler_pty_master::close ()
if (!ForceCloseHandle (to_master))
termios_printf ("error closing to_master %p, %E", to_master);
from_master = to_master = NULL;
+ if (!ForceCloseHandle (get_io_handle_cyg ()))
+ termios_printf ("error closing io_handle_cyg %p, %E", get_io_handle_cyg ());
+ if (!ForceCloseHandle (to_master_cyg))
+ termios_printf ("error closing to_master_cyg %p, %E", to_master_cyg);
+ get_io_handle_cyg () = to_master_cyg = NULL;
ForceCloseHandle (echo_r);
ForceCloseHandle (echo_w);
echo_r = echo_w = NULL;
@@ -1353,7 +1378,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
case FIONREAD:
{
DWORD n;
- if (!::bytes_available (n, to_master))
+ if (!::bytes_available (n, get_io_handle_cyg ()))
{
set_errno (EINVAL);
return -1;
@@ -1523,6 +1548,13 @@ fhandler_pty_master::pty_master_thread ()
termios_printf ("DuplicateHandle (to_master), %E");
goto reply;
}
+ if (!DuplicateHandle (GetCurrentProcess (), to_master_cyg,
+ client, &repl.to_master_cyg,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ termios_printf ("DuplicateHandle (to_master_cyg), %E");
+ goto reply;
+ }
}
reply:
repl.error = GetLastError ();
@@ -1548,6 +1580,40 @@ pty_master_thread (VOID *arg)
return ((fhandler_pty_master *) arg)->pty_master_thread ();
}
+DWORD
+fhandler_pty_master::pty_master_fwd_thread ()
+{
+ DWORD rlen;
+ char outbuf[OUT_BUFFER_SIZE];
+
+ termios_printf("Started.");
+ for (;;)
+ {
+ if (!ReadFile (get_io_handle (), outbuf, sizeof outbuf, &rlen, NULL))
+ {
+ termios_printf ("ReadFile for forwarding failed, %E");
+ break;
+ }
+ ssize_t wlen = rlen;
+ while (rlen>0)
+ {
+ if (!process_opost_output (to_master_cyg, outbuf, wlen, false))
+ {
+ termios_printf ("WriteFile for forwarding failed, %E");
+ break;
+ }
+ rlen -= wlen;
+ }
+ }
+ return 0;
+}
+
+static DWORD WINAPI
+pty_master_fwd_thread (VOID *arg)
+{
+ return ((fhandler_pty_master *) arg)->pty_master_fwd_thread ();
+}
+
bool
fhandler_pty_master::setup ()
{
@@ -1574,7 +1640,7 @@ fhandler_pty_master::setup ()
termios_printf ("can't set output_handle(%p) to non-blocking mode",
get_output_handle ());
- char pipename[sizeof("ptyNNNN-from-master")];
+ char pipename[sizeof("ptyNNNN-to-master-cyg")];
__small_sprintf (pipename, "pty%d-to-master", unit);
res = fhandler_pipe::create (&sec_none, &get_io_handle (), &to_master,
fhandler_pty_common::pipesize, pipename, 0);
@@ -1584,6 +1650,15 @@ fhandler_pty_master::setup ()
goto err;
}
+ __small_sprintf (pipename, "pty%d-to-master-cyg", unit);
+ res = fhandler_pipe::create (&sec_none, &get_io_handle_cyg (), &to_master_cyg,
+ fhandler_pty_common::pipesize, pipename, 0);
+ if (res)
+ {
+ errstr = "output pipe for cygwin";
+ goto err;
+ }
+
ProtectHandle1 (get_io_handle (), from_pty);
__small_sprintf (pipename, "pty%d-echoloop", unit);
@@ -1643,28 +1718,38 @@ fhandler_pty_master::setup ()
errstr = "pty master control thread";
goto err;
}
+ master_fwd_thread = new cygthread (::pty_master_fwd_thread, this, "ptymf");
+ if (!master_fwd_thread)
+ {
+ errstr = "pty master forwarding thread";
+ goto err;
+ }
t.set_from_master (from_master);
t.set_to_master (to_master);
+ t.set_to_master_cyg (to_master_cyg);
t.winsize.ws_col = 80;
t.winsize.ws_row = 25;
t.master_pid = myself->pid;
dev ().parse (DEV_PTYM_MAJOR, unit);
- termios_printf ("this %p, pty%d opened - from_pty %p, to_pty %p", this, unit,
- get_io_handle (), get_output_handle ());
+ termios_printf ("this %p, pty%d opened - from_pty <%p,%p>, to_pty %p",
+ this, unit, get_io_handle (), get_io_handle_cyg (),
+ get_output_handle ());
return true;
err:
__seterrno ();
close_maybe (get_io_handle ());
+ close_maybe (get_io_handle_cyg ());
close_maybe (get_output_handle ());
close_maybe (input_available_event);
close_maybe (output_mutex);
close_maybe (input_mutex);
close_maybe (from_master);
close_maybe (to_master);
+ close_maybe (to_master_cyg);
close_maybe (echo_r);
close_maybe (echo_w);
close_maybe (master_ctl);
@@ -1684,11 +1769,13 @@ fhandler_pty_master::fixup_after_fork (HANDLE parent)
{
t.set_from_master (arch->from_master);
t.set_to_master (arch->to_master);
+ t.set_to_master_cyg (arch->to_master_cyg);
}
arch->dwProcessId = wpid;
}
from_master = arch->from_master;
to_master = arch->to_master;
+ to_master_cyg = arch->to_master_cyg;
report_tty_counts (this, "inherited master", "");
}
@@ -1698,7 +1785,7 @@ fhandler_pty_master::fixup_after_exec ()
if (!close_on_exec ())
fixup_after_fork (spawn_info->parent);
else
- from_master = to_master = NULL;
+ from_master = to_master = to_master_cyg = NULL;
}
BOOL