[PATCH 2/2] termios: Add Capability to Generate SIGINTR and SIGQUIT

Joel Sherrill joel at rtems.org
Wed Oct 2 21:56:05 UTC 2019


This patch adds the ability for termios to send SIGINTR on receipt
of VINTR and SIGQUIT for VKILL. This patch does not alter the default
behavior or force POSIX signal code in just because termios is used.
The application must explicitly enable the POSIX behavior of generating
a signal upon receipt of these characters. This is discussed in the
POSIX standard:

   https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html

Updates #3800.
---
 cpukit/Makefile.am               |  1 +
 cpukit/include/rtems/libio.h     | 94 +++++++++++++++++++++++++++++++++++++---
 cpukit/libcsupport/src/termios.c | 38 ++++++++++++++++
 testsuites/libtests/Makefile.am  | 12 ++++-
 testsuites/libtests/configure.ac |  1 +
 5 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 01ee409..7698fe5 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -250,6 +250,7 @@ librtemscpu_a_SOURCES += libcsupport/src/termios_baudtable.c
 librtemscpu_a_SOURCES += libcsupport/src/termios.c
 librtemscpu_a_SOURCES += libcsupport/src/termiosinitialize.c
 librtemscpu_a_SOURCES += libcsupport/src/termios_num2baud.c
+librtemscpu_a_SOURCES += libcsupport/src/termios_posix_isig_handler.c
 librtemscpu_a_SOURCES += libcsupport/src/termios_setbestbaud.c
 librtemscpu_a_SOURCES += libcsupport/src/termios_setinitialbaud.c
 librtemscpu_a_SOURCES += libcsupport/src/__times.c
diff --git a/cpukit/include/rtems/libio.h b/cpukit/include/rtems/libio.h
index f3b0f2c..27ee078 100644
--- a/cpukit/include/rtems/libio.h
+++ b/cpukit/include/rtems/libio.h
@@ -1880,6 +1880,8 @@ extern const rtems_filesystem_mount_configuration
  */
 /**@{**/
 
+struct rtems_termios_tty;
+
 typedef struct rtems_termios_callbacks {
   int    (*firstOpen)(int major, int minor, void *arg);
   int    (*lastClose)(int major, int minor, void *arg);
@@ -1907,6 +1909,92 @@ rtems_status_code rtems_termios_bufsize (
   size_t raw_output    /* raw output buffer size */
 );
 
+/**
+ * @brief Type for ISIG (VINTR/VKILL) handler
+ *
+ * This type defines the interface to a method which will process
+ * VKILL and VINTR characters. The user can register a handler to
+ * override the default behavior which is to take no special action
+ * on these characters. The POSIX required behavior is to
+ * generate a SIGINTR or SIGQUIT signal. This behavior is implemented if
+ * the user registers the @ref rtems_termios_posix_isig_handler().
+ *
+ * @param c     character that was input
+ * @param tty   termios structure pointer for this input tty
+ *
+ * @return The integer returned is 0 to indicate the character was processed
+ * and 1 if not.
+ */
+typedef int (*rtems_termios_isig_handler)(
+  unsigned char             c,
+  struct rtems_termios_tty *tty
+);
+
+/**
+ * @brief Default handler for ISIG (VINTR/VKILL)
+ *
+ * This handler is installed by default by termios. It performs
+ * no actions on receiving the VINTR and VKILL characters. This is
+ * not POSIX conformant behavior but is the historical RTEMS behavior
+ * and avoid any default dependency on signal processing code.
+ *
+ * @param c     character that was input
+ * @param tty   termios structure pointer for this input tty
+ *
+ * The installed ISIG handler is only invoked if the character is
+ * (VKILL or VINTR) and ISIG is enabled. Thus the handler need only
+ * check the character and perform the appropriate action.
+ *
+ * @return The integer returned is always 0 to indicate that the character
+ *         @a c was not processed.
+ */
+int rtems_termios_default_isig_handler(
+  unsigned char             c,
+  struct rtems_termios_tty *tty
+);
+
+/**
+ * @brief POSIX handler for ISIG (VINTR/VKILL)
+ *
+ * This handler is installed by the used to obtain POSIX behavior
+ * upon receiving the VINTR and VKILL characters.  The POSIX required
+ * behavior is to generate a SIGINTR or SIGQUIT signal if ISIG is enabled.
+ *
+ * @param c     character that was input
+ * @param tty   termios structure pointer for this input tty
+ *
+ * @return The integer returned is 0 to indicate the character was processed
+ * and 1 if not.
+ */
+int rtems_termios_posix_isig_handler(
+  unsigned char             c,
+  struct rtems_termios_tty *tty
+);
+
+/**
+ * @brief Register handler for ISIG (VINTR/VKILL)
+ *
+ * This method is invoked to install an ISIG handler. This may be used
+ * to install @ref rtems_termios_posix_isig_handler() to obtain POSIX
+ * behavior or a custom handler. The handler
+ * @ref rtems_termios_default_isig_handler() is installed by default.
+ *
+ * @param handler entry point of the new ISIG handler
+ *
+ * @return The integer returned is 0 to indicate success and a non-zero
+ *         value otherwise.
+ */
+int rtems_termios_register_isig_handler(
+  rtems_termios_isig_handler handler
+);
+
+
+int rtems_termios_enqueue_raw_characters(
+  void *ttyp,
+  const char *buf,
+  int   len
+);
+
 rtems_status_code rtems_termios_open (
   rtems_device_major_number      major,
   rtems_device_minor_number      minor,
@@ -1930,12 +2018,6 @@ rtems_status_code rtems_termios_ioctl(
   void *arg
 );
 
-int rtems_termios_enqueue_raw_characters(
-  void *ttyp,
-  const char *buf,
-  int   len
-);
-
 int rtems_termios_dequeue_characters(
   void *ttyp,
   int   len
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index 0fc9de45..4f69a75 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -1300,12 +1300,50 @@ iprocEarly (unsigned char c, rtems_termios_tty *tty)
   return c;
 }
 
+static rtems_termios_isig_handler termios_isig_handler =
+   rtems_termios_default_isig_handler;
+
+int rtems_termios_default_isig_handler(
+  unsigned char c,
+  struct rtems_termios_tty *tty
+)
+{
+  return 1;
+}
+
+int rtems_termios_register_isig_handler(
+  rtems_termios_isig_handler handler
+)
+{
+  if (handler == NULL) {
+    return -1;
+  }
+
+  termios_isig_handler = handler;
+  return 0;
+}
+
 /*
  * Process a single input character
  */
 static int
 iproc (unsigned char c, struct rtems_termios_tty *tty)
 {
+  /*
+   * If signals are enabled, then allow possibility of VINTR causing
+   * SIGINTR and VQUIT causing SIGQUIT. Invoke user provided isig handler.
+   */
+  if ((tty->termios.c_lflag & ISIG)) {
+    if ((c == tty->termios.c_cc[VINTR]) || (c == tty->termios.c_cc[VQUIT])) {
+      if ((*termios_isig_handler)(c, tty) == 0) {
+        return 0;
+      }
+    }
+  }
+
+  /*
+   * Perform canonical character processing.
+   */
   if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
     if (c == tty->termios.c_cc[VERASE]) {
       erase (tty, 0);
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 1b80283..4366083 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -1489,7 +1489,17 @@ lib_screens += termios09/termios09.scn
 lib_docs += termios09/termios09.doc
 termios09_SOURCES = termios09/init.c
 termios09_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_termios09) \
-	$(support_includes)
+	$(support_includes) 
+endif
+
+if TEST_termios10
+lib_tests += termios10
+lib_screens += termios10/termios10.scn
+lib_docs += termios10/termios10.doc
+termios10_SOURCES  = termios10/init.c
+termios10_SOURCES += termios03/termios_testdriver_polled.c
+termios10_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_termios10) \
+	$(support_includes) -I$(top_srcdir)/termios03
 endif
 
 if TEST_top
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index c02b42a..b2c2bfa 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -225,6 +225,7 @@ RTEMS_TEST_CHECK([termios06])
 RTEMS_TEST_CHECK([termios07])
 RTEMS_TEST_CHECK([termios08])
 RTEMS_TEST_CHECK([termios09])
+RTEMS_TEST_CHECK([termios10])
 RTEMS_TEST_CHECK([top])
 RTEMS_TEST_CHECK([ttest01])
 RTEMS_TEST_CHECK([tztest])
-- 
1.8.3.1



More information about the devel mailing list