[rtems-libbsd commit] Add telnetd as service to rc.conf.

Chris Johns chrisj at rtems.org
Fri Jul 1 05:50:43 UTC 2016


Module:    rtems-libbsd
Branch:    master
Commit:    65c65bb7a3e981b01e0dfe42dbd62617b867de55
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=65c65bb7a3e981b01e0dfe42dbd62617b867de55

Author:    Chris Johns <chrisj at rtems.org>
Date:      Fri Jul  1 15:49:52 2016 +1000

Add telnetd as service to rc.conf.

---

 libbsd.py                                          |   2 +
 libbsd_waf.py                                      |   2 +
 rtemsbsd/include/machine/rtems-bsd-config.h        |  15 ++
 .../include/machine/rtems-bsd-rc-conf-services.h   |   5 +-
 rtemsbsd/include/rtems/telnetd.h                   |   5 +
 rtemsbsd/telnetd/telnetd-init.c                    |  33 ++++
 rtemsbsd/telnetd/telnetd-service.c                 | 184 +++++++++++++++++++++
 rtemsbsd/telnetd/telnetd.c                         |  70 +++++---
 testsuite/rcconf02/test_main.c                     |  22 +--
 9 files changed, 296 insertions(+), 42 deletions(-)

diff --git a/libbsd.py b/libbsd.py
index e116d05..e8b1034 100755
--- a/libbsd.py
+++ b/libbsd.py
@@ -148,6 +148,8 @@ def rtems(mm):
             'telnetd/des.c',
             'telnetd/pty.c',
             'telnetd/telnetd.c',
+            'telnetd/telnetd-init.c',
+            'telnetd/telnetd-service.c',
             'sys/dev/tsec/if_tsec_nexus.c',
         ],
         mm.generator['source']()
diff --git a/libbsd_waf.py b/libbsd_waf.py
index 4414f1d..ada200d 100644
--- a/libbsd_waf.py
+++ b/libbsd_waf.py
@@ -1115,6 +1115,8 @@ def build(bld):
               'rtemsbsd/telnetd/check_passwd.c',
               'rtemsbsd/telnetd/des.c',
               'rtemsbsd/telnetd/pty.c',
+              'rtemsbsd/telnetd/telnetd-init.c',
+              'rtemsbsd/telnetd/telnetd-service.c',
               'rtemsbsd/telnetd/telnetd.c']
     if bld.get_env()["RTEMS_ARCH"] == "arm":
         source += ['freebsd/sys/mips/mips/in_cksum.c']
diff --git a/rtemsbsd/include/machine/rtems-bsd-config.h b/rtemsbsd/include/machine/rtems-bsd-config.h
index 1f8876c..80e6af8 100644
--- a/rtemsbsd/include/machine/rtems-bsd-config.h
+++ b/rtemsbsd/include/machine/rtems-bsd-config.h
@@ -32,6 +32,8 @@
  *  RTEMS_BSD_CONFIG_NET_PF_UNIX            : Packet Filter.
  *  RTEMS_BSD_CONFIG_NET_IF_LAGG            : Link Aggregetion and Failover.
  *  RTEMS_BSD_CONFIG_NET_IF_VLAN            : Virtual LAN.
+ *  RTEMS_BSD_CONFIG_SERVICE_TELNETD        : Telnet Protocol (TELNET).
+ *   RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE    : Telnet shell task stack size.
  *  RTEMS_BSD_CONFIG_SERVICE_FTPD           : File Transfer Protocol (FTP).
  *  RTEMS_BSD_CONFIG_BSP_CONFIG             : Configure default BSP devices.
  *  RTEMS_BSD_CONFIG_INIT                   : Configure the LibBSD support.
@@ -118,6 +120,17 @@ extern "C" {
 #endif /* RTEMS_BSD_CONFIG_SERVICE_FTPD */
 
 /*
+ * Telnetd
+ */
+#if defined(RTEMS_BSD_CONFIG_SERVICE_TELNETD)
+  #if defined(RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE)
+    #define RTEMS_BSD_CFGDECL_TELNETD_STACK_SIZE \
+      int rtems_telnetd_stack_size = RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE
+  #endif /* RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE */
+  #define RTEMS_BSD_CFGDECL_TELNETD RTEMS_BSD_RC_CONF_SYSINT(rc_conf_telnetd)
+#endif /* RTEMS_BSD_CONFIG_SERVICE_TELNETD */
+
+/*
  * Configure the system.
  */
 #if defined(RTEMS_BSD_CONFIG_INIT)
@@ -145,6 +158,8 @@ extern "C" {
   /*
    * Create the services.
    */
+  RTEMS_BSD_CFGDECL_TELNETD;
+  RTEMS_BSD_CFGDECL_TELNETD_STACK_SIZE;
   RTEMS_BSD_CFGDECL_FTPD;
 #endif /* RTEMS_BSD_CONFIG_INIT */
 
diff --git a/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h b/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h
index 955c9f2..34a8a8b 100644
--- a/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h
+++ b/rtemsbsd/include/machine/rtems-bsd-rc-conf-services.h
@@ -154,8 +154,9 @@ extern void rtems_bsd_rc_conf_print_cmd(rtems_bsd_rc_conf* rc_conf,
 /*
  * Decls for the handlers.
  */
-void rc_conf_net_init(void* arg);    /* Installed by default. */
-void rc_conf_ftpd_init(void* arg);   /* ftpd_enabled="YES" */
+void rc_conf_net_init(void* arg);           /* Installed by default. */
+void rc_conf_telnetd_init(void* arg);       /* telnetd_enabled="YES" */
+void rc_conf_ftpd_init(void* arg);          /* ftpd_enabled="YES" */
 
 /*
  * Added services.
diff --git a/rtemsbsd/include/rtems/telnetd.h b/rtemsbsd/include/rtems/telnetd.h
index a5c8a18..3919d80 100644
--- a/rtemsbsd/include/rtems/telnetd.h
+++ b/rtemsbsd/include/rtems/telnetd.h
@@ -88,6 +88,11 @@ typedef struct {
 } rtems_telnetd_config_table;
 
 /**
+ * @brief Start the Telnet subsystem with the provided configuration.
+ */
+rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config);
+
+/**
  * @brief Telnet configuration.
  *
  * The application must provide this configuration table.  It is used by
diff --git a/rtemsbsd/telnetd/telnetd-init.c b/rtemsbsd/telnetd/telnetd-init.c
new file mode 100644
index 0000000..e723def
--- /dev/null
+++ b/rtemsbsd/telnetd/telnetd-init.c
@@ -0,0 +1,33 @@
+/***********************************************************/
+/*
+ *
+ *  The telnet DAEMON
+ *
+ *  Author: 17,may 2001
+ *
+ *   WORK: fernando.ruiz at ctv.es
+ *   HOME: correo at fernando-ruiz.com
+ *
+ * Copyright (c) 2009 embedded brains GmbH and others.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-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 <rtems/telnetd.h>
+
+rtems_status_code rtems_telnetd_initialize(void)
+{
+  return rtems_telnetd_start(&rtems_telnetd_config);
+}
diff --git a/rtemsbsd/telnetd/telnetd-service.c b/rtemsbsd/telnetd/telnetd-service.c
new file mode 100644
index 0000000..be6e812
--- /dev/null
+++ b/rtemsbsd/telnetd/telnetd-service.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Telnet service. To use add to rc.conf:
+ *
+ * telnetd_enable="YES"
+ * telnet_options="-p 21 -s 32768 -P 8 -L"
+ *
+ * The options defaults are show. The options are:
+ *
+ *  -C conns      : Maximum connections (ptys).
+ *  -P priority   : Telnet thread priority (RTEMS Classis API).
+ *  -L            : Login using /etc/passwd
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define __need_getopt_newlib
+#include <getopt.h>
+
+#include <rtems/telnetd.h>
+#include <machine/rtems-bsd-rc-conf-services.h>
+
+/*
+ * Stack size. Use RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE.
+ */
+extern int rtems_telnetd_stack_size;
+__weak_reference(_rtems_telnetd_stack_size, rtems_telnetd_stack_size);
+int _rtems_telnetd_stack_size;
+
+/*
+ * Condefs always defines this variable.
+ */
+extern int rtems_telnetd_maximum_ptys;
+
+/*
+ * By default no login.
+ */
+static bool telnet_login;
+
+static void
+hydra_telnetd_command(char* device, void* arg)
+{
+  rtems_shell_login_check_t login = NULL;
+  rtems_shell_env_t         shell_env;
+
+  if (telnet_login)
+    login = rtems_shell_login_check;
+
+  rtems_shell_dup_current_env(&shell_env);
+
+  shell_env.devname       = device;
+  shell_env.taskname      = "TELn";
+  shell_env.exit_shell    = false;
+  shell_env.forever       = 0;
+  shell_env.echo          = 0;
+  shell_env.input         = NULL;
+  shell_env.output        = NULL;
+  shell_env.output_append = 0;
+  shell_env.wake_on_end   = 0;
+  shell_env.login_check   = login;
+
+  rtems_shell_main_loop (&shell_env);
+}
+
+static int
+telnetd_service(rtems_bsd_rc_conf* rc_conf)
+{
+  rtems_telnetd_config_table config = {
+    .priority = 100,                  /* Telnet task priority */
+    .stack_size = 32 * 1024,          /* Stack size */
+    .command = hydra_telnetd_command, /* The telnetd command, runs the shell. */
+  };
+  rtems_bsd_rc_conf_argc_argv* aa;
+  int                          conns = 0;
+  int                          r;
+
+  if (rtems_telnetd_stack_size != 0)
+    config.stack_size = rtems_telnetd_stack_size;
+
+  aa = rtems_bsd_rc_conf_argc_argv_create();
+  if (aa == NULL)
+    return -1;
+
+  r = rtems_bsd_rc_conf_find(rc_conf, "telnetd_enable", aa);
+  if (r == 0) {
+    rtems_status_code sc;
+    bool              verbose = false;
+    if (aa->argc == 2 && strcasecmp("YES", aa->argv[1]) == 0) {
+      r = rtems_bsd_rc_conf_find(rc_conf, "telnetd_options", aa);
+      if (r == 0) {
+        struct getopt_data data;
+        char*              end;
+
+        memset(&data, 0, sizeof(data));
+
+        while (true) {
+          int c;
+
+          c = getopt_r(aa->argc, aa->argv, "C:P:Lv", &data);
+          if (c == -1)
+            break;
+
+          switch (c) {
+          case 'C':
+            conns = strtoul(data.optarg, &end, 10);
+            if (conns == 0 || *end != '\0') {
+              fprintf(stderr, "error: telnet: invalid connections countt\n");
+            }
+            else {
+              rtems_telnetd_maximum_ptys = conns;
+            }
+            break;
+          case 'P':
+            config.priority = strtoul(data.optarg, &end, 10);
+            if (config.priority == 0 || *end != '\0') {
+              fprintf(stderr, "error: telnetd: invalid priority\n");
+              config.priority = 100;
+            }
+            break;
+          case 'L':
+            telnet_login = true;
+            break;
+          case 'v':
+            verbose = true;
+            break;
+          case '?':
+          default:
+            fprintf(stderr, "error: telnetd: unknown option: %s\n", data.optarg);
+            break;
+          }
+        }
+      }
+      if (verbose) {
+        printf("telnetd: conns:%lu pri:%lu login:%s\n",
+               rtems_telnetd_maximum_ptys, config.priority,
+               telnet_login == NULL ? "no" : "yes");
+      }
+      sc = rtems_telnetd_start(&config);
+      if (sc != RTEMS_SUCCESSFUL)
+        fprintf(stderr, "error: telnetd: %s\n", rtems_status_text(sc));
+    }
+  }
+
+  return 0;
+}
+
+void
+rc_conf_telnetd_init(void* arg)
+{
+  int r;
+  r = rtems_bsd_rc_conf_service_add("telnetd",
+                                    "after:network;before:ftpd;",
+                                    telnetd_service);
+  if (r < 0)
+    fprintf(stderr, "error: telnetd service add failed: %s\n", strerror(errno));
+}
diff --git a/rtemsbsd/telnetd/telnetd.c b/rtemsbsd/telnetd/telnetd.c
index 50fbe3b..7fe603f 100644
--- a/rtemsbsd/telnetd/telnetd.c
+++ b/rtemsbsd/telnetd/telnetd.c
@@ -87,9 +87,16 @@ rtems_id telnetd_dflt_spawn(
 );
 
 /***********************************************************/
-static rtems_id telnetd_task_id = RTEMS_ID_NONE;
+static rtems_telnetd_config_table* telnetd_config;
+static rtems_id                    telnetd_task_id;
 
-rtems_id (*telnetd_spawn_task)(
+/*
+ * chrisj: this variable was global and with no declared interface in a header
+ *         file and with no means to set it so I have stopped it being global;
+ *         if this breaks any user they will have be to provide a formal
+ *         interface to get this change reverted.
+ */
+static const rtems_id (*telnetd_spawn_task)(
   const char *,
   unsigned,
   unsigned,
@@ -207,24 +214,24 @@ rtems_task_telnetd(void *task_argument)
   };
 
   /* we don't redirect stdio as this probably
-   * was started from the console anyways..
+   * was started from the console anyway ..
    */
   do {
-    if (rtems_telnetd_config.keep_stdio) {
+    if (telnetd_config->keep_stdio) {
       bool start = true;
       char device_name [32];
 
       ttyname_r( 1, device_name, sizeof( device_name));
-      if (rtems_telnetd_config.login_check != NULL) {
+      if (telnetd_config->login_check != NULL) {
         start = rtems_shell_login_prompt(
           stdin,
           stderr,
           device_name,
-          rtems_telnetd_config.login_check
+          telnetd_config->login_check
         );
       }
       if (start) {
-        rtems_telnetd_config.command( device_name, arg->arg);
+        telnetd_config->command( device_name, arg->arg);
       } else {
         syslog(
           LOG_AUTHPRIV | LOG_WARNING,
@@ -244,13 +251,13 @@ rtems_task_telnetd(void *task_argument)
       arg = malloc( sizeof(*arg) );
 
       arg->devname = devname;
-      arg->arg = rtems_telnetd_config.arg;
+      arg->arg = telnetd_config->arg;
       strncpy(arg->peername, peername, sizeof(arg->peername));
 
       telnetd_task_id = telnetd_spawn_task(
         devname,
-        rtems_telnetd_config.priority,
-        rtems_telnetd_config.stack_size,
+        telnetd_config->priority,
+        telnetd_config->stack_size,
         spawned_shell,
         arg
       );
@@ -287,52 +294,65 @@ rtems_task_telnetd(void *task_argument)
   telnetd_task_id = RTEMS_ID_NONE;
 }
 
-rtems_status_code rtems_telnetd_initialize( void)
+rtems_status_code rtems_telnetd_start(const rtems_telnetd_config_table* config)
 {
-  if (telnetd_task_id != RTEMS_ID_NONE) {
+  if (telnetd_config != NULL) {
     fprintf(stderr, "telnetd already started\n");
     return RTEMS_RESOURCE_IN_USE;
   }
 
-  if (rtems_telnetd_config.command == NULL) {
+  if (config->command == NULL) {
     fprintf(stderr, "telnetd setup with invalid command\n");
     return RTEMS_IO_ERROR;
   }
 
+  telnetd_config = calloc(1, sizeof(*telnetd_config));
+  if (telnetd_config == NULL) {
+    fprintf(stderr, "telnetd cannot alloc telnetd config table\n");
+    return RTEMS_NO_MEMORY;
+  }
+
+
   if ( !telnet_pty_initialize() ) {
     fprintf(stderr, "telnetd cannot initialize PTY driver\n");
+    free(telnetd_config);
+    telnetd_config = NULL;
     return RTEMS_IO_ERROR;
   }
 
+  *telnetd_config = *config;
+
   /* Check priority */
-  if (rtems_telnetd_config.priority < 2) {
-    rtems_telnetd_config.priority = 100;
+  if (telnetd_config->priority < 2) {
+    telnetd_config->priority = 100;
   }
 
   /* Check stack size */
-  if (rtems_telnetd_config.stack_size <= 0) {
-    rtems_telnetd_config.stack_size = (size_t)32 * 1024;
+  if (telnetd_config->stack_size <= 0) {
+    telnetd_config->stack_size = (size_t)32 * 1024;
   }
 
   /* Spawn task */
   telnetd_task_id = telnetd_spawn_task(
     "TNTD",
-    rtems_telnetd_config.priority,
-    rtems_telnetd_config.stack_size,
+    telnetd_config->priority,
+    telnetd_config->stack_size,
     rtems_task_telnetd,
     0
   );
   if (telnetd_task_id == RTEMS_ID_NONE) {
+    free(telnetd_config);
+    telnetd_config = NULL;
     return RTEMS_IO_ERROR;
   }
 
   /* Print status */
-  if (!rtems_telnetd_config.keep_stdio) {
+  if (!telnetd_config->keep_stdio) {
     fprintf(
       stderr,
       "telnetd started with stacksize = %u and priority = %d\n",
-      (unsigned) rtems_telnetd_config.stack_size,
-      (unsigned) rtems_telnetd_config.priority
+      (unsigned) telnetd_config->stack_size,
+      (unsigned) telnetd_config->priority
     );
   }
 
@@ -386,17 +406,17 @@ spawned_shell(void *targ)
   #endif
 
   /* call their routine */
-  if (rtems_telnetd_config.login_check != NULL) {
+  if (telnetd_config->login_check != NULL) {
     start = rtems_shell_login_prompt(
       stdin,
       stderr,
       arg->devname,
-      rtems_telnetd_config.login_check
+      telnetd_config->login_check
     );
     login_failed = !start;
   }
   if (start) {
-    rtems_telnetd_config.command( arg->devname, arg->arg);
+    telnetd_config->command( arg->devname, arg->arg);
   }
 
   stdin  = ostd[0];
diff --git a/testsuite/rcconf02/test_main.c b/testsuite/rcconf02/test_main.c
index 7cb9999..8695e56 100644
--- a/testsuite/rcconf02/test_main.c
+++ b/testsuite/rcconf02/test_main.c
@@ -69,10 +69,6 @@
 #include <rtems/console.h>
 #include <rtems/shell.h>
 
-#if DEFINE_FOR_TESTING
-#define RCCONF02_HAS_SHELL
-#endif
-
 #define TEST_NAME "LIBBSD RC.CONF 2"
 
 #define IFACE_IPV4(iface) \
@@ -121,6 +117,9 @@ static const char* rc_conf_text =                          \
   "\n"                                                     \
   "dhcpcd_options=\"-h foobar\"\n"                         \
   "\n"                                                     \
+  "telnetd_enable=\"YES\"\n"                               \
+  "telnetd_options=\"-v -C 10 -P 50 -L\"\n"                \
+  "\n"                                                     \
   "ftpd_enable=\"YES\"\n"                                  \
   "ftpd_options=\"-v -p 21 -C 10 -P 150 -L -I 10 -R /\"\n" \
   "n";
@@ -153,7 +152,6 @@ test_main(void)
 {
   test_rc_conf_script();
 
-#if defined(RCCONF02_HAS_SHELL)
   rtems_shell_init(
     "SHLL",
     32 * 1024,
@@ -163,19 +161,10 @@ test_main(void)
     true,
     NULL
     );
-#else
-  printf("RCCONF02 sleeping for 10s\n");
-  sleep(10);
-#endif /* RCCONF02_HAS_SHELL */
 
   exit(0);
 }
 
-/*
- * Optional shell for testing this test.
- */
-#if defined(RCCONF02_HAS_SHELL)
-
 #define CONFIGURE_SHELL_COMMANDS_INIT
 
 #include <bsp/irq-info.h>
@@ -214,9 +203,12 @@ test_main(void)
 #define CONFIGURE_SHELL_COMMAND_SHUTDOWN
 
 #include <rtems/shellconfig.h>
-#endif /* RCCONF02_HAS_SHELL */
 
 #define RTEMS_BSD_CONFIG_BSP_CONFIG
+#define RTEMS_BSD_CONFIG_SERVICE_TELNETD
+#define RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE (16 * 1024)
 #define RTEMS_BSD_CONFIG_SERVICE_FTPD
 
+#define CONFIGURE_MAXIMUM_DRIVERS 32
+
 #include <rtems/bsd/test/default-init.h>




More information about the vc mailing list