[PATCH] telnetd: Remove keep stdio feature
Sebastian Huber
sebastian.huber at embedded-brains.de
Tue Oct 9 12:51:59 UTC 2018
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 | 22 +++--
cpukit/telnetd/telnetd.c | 112 ++++++++---------------
testsuites/libtests/Makefile.am | 12 +++
testsuites/libtests/configure.ac | 1 +
testsuites/libtests/telnetd01/init.c | 136 ++++++++++++++++++++++++++++
testsuites/libtests/telnetd01/telnetd01.doc | 24 +++++
testsuites/libtests/telnetd01/telnetd01.scn | 12 +++
7 files changed, 239 insertions(+), 80 deletions(-)
create mode 100644 testsuites/libtests/telnetd01/init.c
create mode 100644 testsuites/libtests/telnetd01/telnetd01.doc
create mode 100644 testsuites/libtests/telnetd01/telnetd01.scn
diff --git a/cpukit/include/rtems/telnetd.h b/cpukit/include/rtems/telnetd.h
index 2339bad8b6..9f6ea614fe 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,14 @@ 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_NO_MEMORY Not enough resources to start the Telnet server.
*/
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 650b0f9418..f03dd0cabb 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_NO_MEMORY;
}
+ syslog(LOG_DAEMON | LOG_INFO, "telnetd: started successfully");
return RTEMS_SUCCESSFUL;
}
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 52bbc3e3fb..240b04c74c 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 c529b27660..303a165731 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 0000000000..8ed0829117
--- /dev/null
+++ b/testsuites/libtests/telnetd01/init.c
@@ -0,0 +1,136 @@
+/*
+ * 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 bool login_check(const char *user, const char *pass)
+{
+ rtems_test_assert(
+ strcmp(user, "anonymous") == 0 || strcmp(user, "user") == 0
+ );
+
+ if (pass != NULL) {
+ rtems_test_assert(
+ strcmp(pass, "anonymous") == 0 || strcmp(pass, "pass") == 0
+ );
+ printf("login check (2): user \"%s\", pass \"%s\"\n", user, pass);
+ return true;
+ } else {
+ printf("login check (1): user \"%s\"\n", user);
+ return strcmp(user, "anonymous") == 0;
+ }
+}
+
+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,
+ .stack_size = SIZE_MAX
+ };
+ rtems_status_code sc;
+
+ sc = rtems_telnetd_start(&config);
+ rtems_test_assert(sc == RTEMS_NO_MEMORY);
+}
+
+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 0000000000..fe1a4d31a3
--- /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 0000000000..61be41bb72
--- /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_UNSATISFIED)
+syslog: telnetd: cannot create server task
+syslog: telnetd: started successfully
+syslog: telnetd: already started
+
+*** END OF TEST TELNETD 1 ***
--
2.16.4
More information about the devel
mailing list