From 41946df6111b6daf93518b22ca49c54544c77599 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 18 Sep 2003 18:54:48 +0000 Subject: [PATCH] * fhandler_tty.cc (fhandler_pty_master::process_slave_output): Handle buf == NULL as flushing the buffer. (fhandler_tty_slave::read): Handle ptr == NULL as flushing the buffer. (fhandler_tty_slave::tcflush): Implement input queue flushing by calling read with NULL buffer. (fhandler_pty_master::tcflush): Ditto, calling process_slave_output. * termios.cc (tcflush): Check for legal `queue' value. Return EINVAL otherwise. --- winsup/cygwin/ChangeLog | 11 ++++++ winsup/cygwin/fhandler_tty.cc | 72 +++++++++++++++++++++++++++++------ winsup/cygwin/termios.cc | 2 + 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 62c776a38..036896a0b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2003-09-18 Corinna Vinschen + + * fhandler_tty.cc (fhandler_pty_master::process_slave_output): + Handle buf == NULL as flushing the buffer. + (fhandler_tty_slave::read): Handle ptr == NULL as flushing the buffer. + (fhandler_tty_slave::tcflush): Implement input queue flushing by + calling read with NULL buffer. + (fhandler_pty_master::tcflush): Ditto, calling process_slave_output. + * termios.cc (tcflush): Check for legal `queue' value. Return + EINVAL otherwise. + 2003-09-16 Brian Ford * syscalls.cc (gethostid): Add lpFreeBytesAvailable argument to diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 9a1db30da..1bb3d87a7 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -252,7 +252,8 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on \r\n conversion. Note that we already checked for FLUSHO and output_stopped at the time that we read the character, so we don't check again here. */ - buf[0] = '\n'; + if (buf) + buf[0] = '\n'; need_nl = 0; rc = 1; goto out; @@ -290,6 +291,9 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on break; if (hit_eof ()) goto out; + /* DISCARD (FLUSHO) and tcflush can finish here. */ + if (n == 0 && (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)) + goto out; if (n == 0 && is_nonblocking ()) { set_errno (EAGAIN); @@ -309,7 +313,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on if (output_done_event != NULL) SetEvent (output_done_event); - if (get_ttyp ()->ti.c_lflag & FLUSHO) + if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf) continue; char *optr; @@ -697,7 +701,9 @@ fhandler_tty_slave::read (void *ptr, size_t& len) termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ()); - if ((get_ttyp ()->ti.c_lflag & ICANON)) + if (!ptr) /* Indicating tcflush(). */ + time_to_wait = 0; + else if ((get_ttyp ()->ti.c_lflag & ICANON)) time_to_wait = INFINITE; else { @@ -718,7 +724,7 @@ fhandler_tty_slave::read (void *ptr, size_t& len) w4[0] = signal_arrived; w4[1] = input_available_event; - DWORD waiter = INFINITE; + DWORD waiter = !ptr ? 0 : INFINITE; while (len) { rc = WaitForMultipleObjects (2, w4, FALSE, waiter); @@ -761,7 +767,11 @@ fhandler_tty_slave::read (void *ptr, size_t& len) bytes_in_pipe = 0; } - if (!vmin && !time_to_wait) + /* On first peek determine no. of bytes to flush. */ + if (!ptr && len == UINT_MAX) + len = (size_t) bytes_in_pipe; + + if (ptr && !vmin && !time_to_wait) { ReleaseMutex (input_mutex); len = (size_t) bytes_in_pipe; @@ -770,7 +780,7 @@ fhandler_tty_slave::read (void *ptr, size_t& len) readlen = min (bytes_in_pipe, min (len, sizeof (buf))); - if (vmin && readlen > (unsigned) vmin) + if (ptr && vmin && readlen > (unsigned) vmin) readlen = vmin; DWORD n = 0; @@ -796,8 +806,11 @@ fhandler_tty_slave::read (void *ptr, size_t& len) { len -= n; totalread += n; - memcpy (ptr, buf, n); - ptr = (char *) ptr + n; + if (ptr) + { + memcpy (ptr, buf, n); + ptr = (char *) ptr + n; + } } } @@ -806,6 +819,13 @@ fhandler_tty_slave::read (void *ptr, size_t& len) ReleaseMutex (input_mutex); + if (!ptr) + { + if (!bytes_in_pipe) + break; + continue; + } + if (get_ttyp ()->read_retval < 0) // read error { set_errno (-get_ttyp ()->read_retval); @@ -970,9 +990,25 @@ fhandler_tty_slave::tcsetattr (int, const struct termios *t) } int -fhandler_tty_slave::tcflush (int) +fhandler_tty_slave::tcflush (int queue) { - return 0; + int ret = 0; + + termios_printf ("tcflush(%d) handle %p", queue, get_handle ()); + + if (queue == TCIFLUSH || queue == TCIOFLUSH) + { + size_t len = UINT_MAX; + read (NULL, len); + ret = len >= 0; + } + if (queue == TCOFLUSH || queue == TCIOFLUSH) + { + /* do nothing for now. */ + } + + termios_printf ("%d=tcflush(%d)", ret, queue); + return ret; } int @@ -1174,9 +1210,21 @@ fhandler_pty_master::tcsetattr (int, const struct termios *t) } int -fhandler_pty_master::tcflush (int) +fhandler_pty_master::tcflush (int queue) { - return 0; + int ret = 0; + + termios_printf ("tcflush(%d) handle %p", queue, get_handle ()); + + if (queue == TCIFLUSH || queue == TCIOFLUSH) + ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0); + else if (queue == TCIFLUSH || queue == TCIOFLUSH) + { + /* do nothing for now. */ + } + + termios_printf ("%d=tcflush(%d)", ret, queue); + return ret; } int diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc index 60ef9641f..c82f771b7 100644 --- a/winsup/cygwin/termios.cc +++ b/winsup/cygwin/termios.cc @@ -79,6 +79,8 @@ tcflush (int fd, int queue) if (!cfd->is_tty ()) set_errno (ENOTTY); + else if (queue != TCIFLUSH && queue != TCOFLUSH && queue != TCIOFLUSH) + set_errno (EINVAL); else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof) res = cfd->tcflush (queue);