summaryrefslogtreecommitdiffstats
path: root/rtemsbsd/telnetd/telnetd-service.c
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2016-07-01 15:49:52 +1000
committerChris Johns <chrisj@rtems.org>2016-07-01 15:49:52 +1000
commit65c65bb7a3e981b01e0dfe42dbd62617b867de55 (patch)
tree1b2b9050d7cbf77729ce55df2641fcb5810b4e18 /rtemsbsd/telnetd/telnetd-service.c
parentAdd ftpd initailize comment. (diff)
downloadrtems-libbsd-65c65bb7a3e981b01e0dfe42dbd62617b867de55.tar.bz2
Add telnetd as service to rc.conf.
Diffstat (limited to 'rtemsbsd/telnetd/telnetd-service.c')
-rw-r--r--rtemsbsd/telnetd/telnetd-service.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/rtemsbsd/telnetd/telnetd-service.c b/rtemsbsd/telnetd/telnetd-service.c
new file mode 100644
index 00000000..be6e8123
--- /dev/null
+++ b/rtemsbsd/telnetd/telnetd-service.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016 Chris Johns <chrisj@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));
+}