Index: cpukit/libcsupport/src/termios.c
===================================================================
--- cpukit/libcsupport/src/termios.c	(revision 1055ff20202e14d6ff253a79ac5f9c95a24603c3)
+++ cpukit/libcsupport/src/termios.c	(revision 791469bd4fb1eba09ea8464795f100d7dd09379e)
@@ -1571,6 +1571,8 @@
       /* continue processing new character */
       if (tty->termios.c_lflag & ICANON) {
-        if (siproc (c, tty))
-          wait = false;
+        if (siproc (c, tty)) {
+          /* In canonical mode, input is made available line by line */
+          return;
+        }
       } else {
         siproc (c, tty);
Index: testsuites/libtests/termios09/init.c
===================================================================
--- testsuites/libtests/termios09/init.c	(revision 1055ff20202e14d6ff253a79ac5f9c95a24603c3)
+++ testsuites/libtests/termios09/init.c	(revision 791469bd4fb1eba09ea8464795f100d7dd09379e)
@@ -37,4 +37,6 @@
 #define OUTPUT_BUFFER_SIZE 64
 
+#define INPUT_BUFFER_SIZE 64
+
 static const char * const paths[DEVICE_COUNT] = {
   "/interrupt",
@@ -48,5 +50,7 @@
   size_t output_count;
   char output_buf[OUTPUT_BUFFER_SIZE];
-  int input_char;
+  size_t input_head;
+  size_t input_tail;
+  unsigned char input_buf[INPUT_BUFFER_SIZE];
   int callback_counter;
 } device_context;
@@ -65,6 +69,5 @@
       .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Interrupt")
     }, {
-      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Polled"),
-      .input_char = -1
+      .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Polled")
     }
   }
@@ -113,7 +116,12 @@
 {
   device_context *dev = (device_context *) base;
-  int c = dev->input_char;
-
-  dev->input_char = -1;
+  int c;
+
+  if (dev->input_head != dev->input_tail) {
+    c = dev->input_buf[dev->input_head];
+    dev->input_head = (dev->input_head + 1) % INPUT_BUFFER_SIZE;
+  } else {
+    c = -1;
+  }
 
   return c;
@@ -188,10 +196,14 @@
 static void input(test_context *ctx, size_t i, char c)
 {
+  device_context *dev = &ctx->devices[i];
+
   switch (i) {
     case INTERRUPT:
-      rtems_termios_enqueue_raw_characters(ctx->devices[i].tty, &c, sizeof(c));
+      rtems_termios_enqueue_raw_characters(dev->tty, &c, sizeof(c));
       break;
     case POLLED:
-      ctx->devices[i].input_char = (unsigned char) c;
+      dev->input_buf[dev->input_tail] = (unsigned char) c;
+      dev->input_tail = (dev->input_tail + 1) % INPUT_BUFFER_SIZE;
+      rtems_test_assert(dev->input_head != dev->input_tail);
       break;
     default:
@@ -524,9 +536,11 @@
   rtems_test_assert(dev->callback_counter == 1);
 
+  n = read(ctx->fds[i], buf, 2);
+  rtems_test_assert(n == 1);
+  rtems_test_assert(buf[0] == '\n');
   n = read(ctx->fds[i], buf, 3);
-  rtems_test_assert(n == 3);
-  rtems_test_assert(buf[0] == '\n');
-  rtems_test_assert(buf[1] == 'a');
-  rtems_test_assert(buf[2] == '\n');
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'a');
+  rtems_test_assert(buf[1] == '\n');
 
   input(ctx, i, '\4');
@@ -539,9 +553,13 @@
   rtems_test_assert(dev->callback_counter == 2);
 
-  n = read(ctx->fds[i], buf, 2);
+  n = read(ctx->fds[i], buf, 1);
+  rtems_test_assert(n == 0);
+
+  n = read(ctx->fds[i], buf, 3);
   rtems_test_assert(n == 2);
   rtems_test_assert(buf[0] == 'b');
   rtems_test_assert(buf[1] == '\n');
 
+  /* EOL */
   input(ctx, i, '1');
   rtems_test_assert(dev->callback_counter == 3);
@@ -553,10 +571,13 @@
   rtems_test_assert(dev->callback_counter == 3);
 
+  n = read(ctx->fds[i], buf, 2);
+  rtems_test_assert(n == 1);
+  rtems_test_assert(buf[0] == '1');
   n = read(ctx->fds[i], buf, 3);
-  rtems_test_assert(n == 3);
-  rtems_test_assert(buf[0] == '1');
-  rtems_test_assert(buf[1] == 'c');
-  rtems_test_assert(buf[2] == '\n');
-
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'c');
+  rtems_test_assert(buf[1] == '\n');
+
+  /* EOL2 */
   input(ctx, i, '2');
   rtems_test_assert(dev->callback_counter == 4);
@@ -568,9 +589,11 @@
   rtems_test_assert(dev->callback_counter == 4);
 
+  n = read(ctx->fds[i], buf, 2);
+  rtems_test_assert(n == 1);
+  rtems_test_assert(buf[0] == '2');
   n = read(ctx->fds[i], buf, 3);
-  rtems_test_assert(n == 3);
-  rtems_test_assert(buf[0] == '2');
-  rtems_test_assert(buf[1] == 'd');
-  rtems_test_assert(buf[2] == '\n');
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'd');
+  rtems_test_assert(buf[1] == '\n');
 
   for (j = 0; j < 255; ++j) {
@@ -589,4 +612,36 @@
   dev->tty->tty_rcv.sw_arg = NULL;
   set_veol_veol2(ctx, i, '\0', '\0');
+  clear_set_lflag(ctx, i, ICANON, 0);
+}
+
+static void test_read_icanon(test_context *ctx, size_t i)
+{
+  ssize_t n;
+  char buf[3];
+
+  clear_set_lflag(ctx, i, 0, ICANON);
+
+  input(ctx, i, 'a');
+  input(ctx, i, '\n');
+  input(ctx, i, 'b');
+  input(ctx, i, '\n');
+  input(ctx, i, 'c');
+  input(ctx, i, '\n');
+
+  n = read(ctx->fds[i], buf, 3);
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'a');
+  rtems_test_assert(buf[1] == '\n');
+
+  n = read(ctx->fds[i], buf, 3);
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'b');
+  rtems_test_assert(buf[1] == '\n');
+
+  n = read(ctx->fds[i], buf, 3);
+  rtems_test_assert(n == 2);
+  rtems_test_assert(buf[0] == 'c');
+  rtems_test_assert(buf[1] == '\n');
+
   clear_set_lflag(ctx, i, ICANON, 0);
 }
@@ -1107,4 +1162,6 @@
   test_rx_callback(ctx);
   test_rx_callback_icanon(ctx);
+  test_read_icanon(ctx, INTERRUPT);
+  test_read_icanon(ctx, POLLED);
   test_onlret(ctx);
   test_onlcr(ctx);
