[rtems commit] telnetd: Remove keep stdio feature

Sebastian Huber sebh at rtems.org
Wed Oct 10 12:06:44 UTC 2018


Module:    rtems
Branch:    master
Commit:    629faf95046cddedc161ba9bc43fda925ca04ee5
Changeset: http://git.rtems.org/rtems/commit/?id=629faf95046cddedc161ba9bc43fda925ca04ee5

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Oct  9 14:47:02 2018 +0200

telnetd: Remove keep stdio feature

The Telnet service started via rtems_telnetd_start() had a keep stdio
feature.  This just created a task and executed the command function in
a loop.  For this kind of service we do not library support.  This can
be done by an application task on its own.  Remove this feature and
provide only the real Telnet server functionality.

Use syslog() for error and status messages.

Add test program for the Telnet server.

Close #3542.

---

 cpukit/include/rtems/telnetd.h              |  23 ++++--
 cpukit/telnetd/telnetd.c                    | 112 ++++++++++----------------
 testsuites/libtests/Makefile.am             |  12 +++
 testsuites/libtests/configure.ac            |   1 +
 testsuites/libtests/telnetd01/init.c        | 118 ++++++++++++++++++++++++++++
 testsuites/libtests/telnetd01/telnetd01.doc |  24 ++++++
 testsuites/libtests/telnetd01/telnetd01.scn |  12 +++
 7 files changed, 222 insertions(+), 80 deletions(-)

diff --git a/cpukit/include/rtems/telnetd.h b/cpukit/include/rtems/telnetd.h
index 2339bad..e662874 100644
--- a/cpukit/include/rtems/telnetd.h
+++ b/cpukit/include/rtems/telnetd.h
@@ -59,13 +59,14 @@ typedef struct {
   /**
    * @brief Task priority.
    *
-   * If this parameter is equal to zero, then the priority of network task is
-   * used or 100 if this priority is less than two.
+   * Use 0 for the default value.
    */
   rtems_task_priority priority;
 
   /**
    * @brief Task stack size.
+   *
+   * Use 0 for the default value.
    */
   size_t stack_size;
 
@@ -77,12 +78,10 @@ typedef struct {
   rtems_shell_login_check_t login_check;
 
   /**
-   * @brief Keep standard IO of the caller.
+   * @brief This is an obsolete configuration option.
    *
-   * Telnet takes over the standard input, output and error associated with
-   * task, if this parameter is set to @c true.  In this case, it will @b not
-   * listen on any sockets.  When this parameter is @c false, Telnet will
-   * create other tasks for the shell which listen on sockets.
+   * It must be set to false, otherwise rtems_telnetd_start() will do nothing
+   * and returns with a status of RTEMS_NOT_IMPLEMENTED.
    */
   bool keep_stdio;
 
@@ -96,7 +95,15 @@ typedef struct {
 } rtems_telnetd_config_table;
 
 /**
- * @brief Start the Telnet subsystem with the provided configuration.
+ * @brief Starts the Telnet server using the provided configuration.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_INVALID_ADDRESS The command function in the configuration is
+ *   @c NULL.
+ * @retval RTEMS_RESOURCE_IN_USE The Telnet server was already started.
+ * @retval RTEMS_NOT_IMPLEMENTED The keep stdio configuration option is true.
+ * @retval RTEMS_UNSATISFIED Not enough resources to start the Telnet server or
+ *   task priority in configuration is invalid.
  */
 rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table *config);
 
diff --git a/cpukit/telnetd/telnetd.c b/cpukit/telnetd/telnetd.c
index 650b0f9..56e48b9 100644
--- a/cpukit/telnetd/telnetd.c
+++ b/cpukit/telnetd/telnetd.c
@@ -234,67 +234,43 @@ rtems_task_telnetd(void *task_argument)
    * was started from the console anyway ..
    */
   do {
-    if (ctx->config.keep_stdio) {
-      bool start = true;
-      char device_name [32];
-
-      ttyname_r( 1, device_name, sizeof( device_name));
-      if (ctx->config.login_check != NULL) {
-        start = rtems_shell_login_prompt(
-          stdin,
-          stderr,
-          device_name,
-          ctx->config.login_check
-        );
-      }
-      if (start) {
-        ctx->config.command( device_name, ctx->config.arg);
-      } else {
-        syslog(
-          LOG_AUTHPRIV | LOG_WARNING,
-          "telnetd: to many wrong passwords entered from %s",
-          device_name
-        );
-      }
-    } else {
-      arg = grab_a_Connection(ctx, des_socket, &srv, peername,
-        sizeof(peername));
-
-      if (arg == NULL) {
-        /* if something went wrong, sleep for some time */
-        sleep(10);
-        continue;
-      }
+    arg = grab_a_Connection(ctx, des_socket, &srv, peername,
+      sizeof(peername));
 
-      strncpy(arg->peername, peername, sizeof(arg->peername));
-
-      task_id = telnetd_spawn_task(
-        arg->pty.name,
-        ctx->config.priority,
-        ctx->config.stack_size,
-        spawned_shell,
-        arg
-      );
-      if (task_id == RTEMS_ID_NONE) {
-        FILE *dummy;
-
-        if ( telnetd_spawn_task != telnetd_dflt_spawn ) {
-          fprintf(stderr,"Telnetd: Unable to spawn child task\n");
-        }
-
-        /* hmm - the pty driver slot can only be
-         * released by opening and subsequently
-         * closing the PTY - this also closes
-         * the underlying socket. So we mock up
-         * a stream...
-         */
+    if (arg == NULL) {
+      /* if something went wrong, sleep for some time */
+      sleep(10);
+      continue;
+    }
+
+    strncpy(arg->peername, peername, sizeof(arg->peername));
+
+    task_id = telnetd_spawn_task(
+      arg->pty.name,
+      ctx->config.priority,
+      ctx->config.stack_size,
+      spawned_shell,
+      arg
+    );
+    if (task_id == RTEMS_ID_NONE) {
+      FILE *dummy;
 
-        if ( !(dummy=fopen(arg->pty.name,"r+")) )
-          perror("Unable to dummy open the pty, losing a slot :-(");
-        release_a_Connection(ctx, arg->pty.name, peername, &dummy, 1);
-        free(arg);
-        sleep(2); /* don't accept connections too fast */
+      if ( telnetd_spawn_task != telnetd_dflt_spawn ) {
+        fprintf(stderr,"Telnetd: Unable to spawn child task\n");
       }
+
+      /* hmm - the pty driver slot can only be
+       * released by opening and subsequently
+       * closing the PTY - this also closes
+       * the underlying socket. So we mock up
+       * a stream...
+       */
+
+      if ( !(dummy=fopen(arg->pty.name,"r+")) )
+        perror("Unable to dummy open the pty, losing a slot :-(");
+      release_a_Connection(ctx, arg->pty.name, peername, &dummy, 1);
+      free(arg);
+      sleep(2); /* don't accept connections too fast */
     }
   } while(1);
 
@@ -313,12 +289,12 @@ rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config)
   rtems_id task_id;
 
   if (config->command == NULL) {
-    fprintf(stderr, "telnetd setup with invalid command\n");
-    return RTEMS_IO_ERROR;
+    syslog(LOG_DAEMON | LOG_ERR, "telnetd: configuration with invalid command");
+    return RTEMS_INVALID_ADDRESS;
   }
 
   if (ctx->config.command != NULL) {
-    fprintf(stderr, "telnetd already started\n");
+    syslog(LOG_DAEMON | LOG_ERR, "telnetd: already started");
     return RTEMS_RESOURCE_IN_USE;
   }
 
@@ -353,19 +329,11 @@ rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config)
   );
   if (task_id == RTEMS_ID_NONE) {
     ctx->config.command = NULL;
-    return RTEMS_IO_ERROR;
-  }
-
-  /* Print status */
-  if (!ctx->config.keep_stdio) {
-    fprintf(
-      stderr,
-      "telnetd started with stacksize = %u and priority = %d\n",
-      (unsigned) ctx->config.stack_size,
-      (unsigned) ctx->config.priority
-    );
+    syslog(LOG_DAEMON | LOG_ERR, "telnetd: cannot create server task");
+    return RTEMS_UNSATISFIED;
   }
 
+  syslog(LOG_DAEMON | LOG_INFO, "telnetd: started successfully");
   return RTEMS_SUCCESSFUL;
 }
 
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 52bbc3e..240b04c 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -1134,6 +1134,18 @@ tar03_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_tar03) \
 	$(support_includes)
 endif
 
+if NETTESTS
+if TEST_telnetd01
+lib_tests += telnetd01
+lib_screens += telnetd01/telnetd01.scn
+lib_docs += telnetd01/telnetd01.doc
+telnetd01_SOURCES = telnetd01/init.c
+telnetd01_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_telnetd01) \
+	$(support_includes) -I$(RTEMS_SOURCE_ROOT)/cpukit/libnetworking
+telnetd01_LDADD = $(RTEMS_ROOT)cpukit/libtelnetd.a $(LDADD)
+endif
+endif
+
 if TEST_termios
 lib_tests += termios
 termios_SOURCES = termios/init.c
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index c529b27..303a165 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -208,6 +208,7 @@ RTEMS_TEST_CHECK([syscall01])
 RTEMS_TEST_CHECK([tar01])
 RTEMS_TEST_CHECK([tar02])
 RTEMS_TEST_CHECK([tar03])
+RTEMS_TEST_CHECK([telnetd01])
 RTEMS_TEST_CHECK([termios])
 RTEMS_TEST_CHECK([termios01])
 RTEMS_TEST_CHECK([termios02])
diff --git a/testsuites/libtests/telnetd01/init.c b/testsuites/libtests/telnetd01/init.c
new file mode 100644
index 0000000..f2243d9
--- /dev/null
+++ b/testsuites/libtests/telnetd01/init.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/telnetd.h>
+
+#include <tmacros.h>
+
+const char rtems_test_name[] = "TELNETD 1";
+
+struct rtems_bsdnet_config rtems_bsdnet_config;
+
+static void command(char *device_name, void *arg)
+{
+}
+
+static void test_command_null(void)
+{
+  static const rtems_telnetd_config_table config = {
+    .command = NULL
+  };
+  rtems_status_code sc;
+
+  sc = rtems_telnetd_start(&config);
+  rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);
+}
+
+static void test_cannot_start_server_task(void)
+{
+  static const rtems_telnetd_config_table config = {
+    .command = command,
+    .priority = UINT32_MAX
+  };
+  rtems_status_code sc;
+
+  sc = rtems_telnetd_start(&config);
+  rtems_test_assert(sc == RTEMS_UNSATISFIED);
+}
+
+static void test_successful_start(void)
+{
+  static const rtems_telnetd_config_table config = {
+    .command = command,
+    .stack_size = RTEMS_MINIMUM_STACK_SIZE
+  };
+  rtems_status_code sc;
+
+  sc = rtems_telnetd_start(&config);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_already_started(void)
+{
+  static const rtems_telnetd_config_table config = {
+    .command = command
+  };
+  rtems_status_code sc;
+
+  sc = rtems_telnetd_start(&config);
+  rtems_test_assert(sc == RTEMS_RESOURCE_IN_USE);
+}
+
+static rtems_task Init(rtems_task_argument argument)
+{
+  int rv;
+
+  TEST_BEGIN();
+
+  rv = rtems_bsdnet_initialize_network();
+  rtems_test_assert(rv == 0);
+
+  test_command_null();
+  test_cannot_start_server_task();
+  test_successful_start();
+  test_already_started();
+
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_INIT
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32
+
+#define CONFIGURE_MAXIMUM_TASKS 7
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/libtests/telnetd01/telnetd01.doc b/testsuites/libtests/telnetd01/telnetd01.doc
new file mode 100644
index 0000000..fe1a4d3
--- /dev/null
+++ b/testsuites/libtests/telnetd01/telnetd01.doc
@@ -0,0 +1,24 @@
+# 
+# Copyright (c) 2018 embedded brains GmbH.  All rights reserved.
+# 
+#  embedded brains GmbH
+#  Dornierstr. 4
+#  82178 Puchheim
+#  Germany
+#  <rtems at embedded-brains.de>
+# 
+# The license and distribution terms for this file may be
+# found in the file LICENSE in this distribution or at
+# http://www.rtems.org/license/LICENSE.
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: telnetd01
+
+directives:
+
+  - rtems_telnetd_start()
+
+concepts:
+
++ Check if Telnet server works.
diff --git a/testsuites/libtests/telnetd01/telnetd01.scn b/testsuites/libtests/telnetd01/telnetd01.scn
new file mode 100644
index 0000000..2dc2c60
--- /dev/null
+++ b/testsuites/libtests/telnetd01/telnetd01.scn
@@ -0,0 +1,12 @@
+*** BEGIN OF TEST TELNETD 1 ***
+*** TEST VERSION: 5.0.0.dc32b6aa0807fb70f9b26bc0bc6e164ddb49bd3a
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_NETWORKING
+*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 9670d7541e0621915e521fe76e7bb33de8cee661, Newlib d13c84eb07e35984bf7a974cd786a6cdac29e6b9)
+syslog: telnetd: configuration with invalid command
+Telnetd: spawning task failed (status: RTEMS_INVALID_PRIORITY)
+syslog: telnetd: cannot create server task
+syslog: telnetd: started successfully
+syslog: telnetd: already started
+
+*** END OF TEST TELNETD 1 ***




More information about the vc mailing list