From 7cc856ea2f1808e98387ea66537ecbc6c3de2f88 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 19 Mar 2011 21:04:13 +0000 Subject: Move nuttx/netutils to apps/netutils git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3401 42af7a65-404d-4744-a932-0658087f49c3 --- apps/netutils/telnetd/Makefile | 94 ++++++++ apps/netutils/telnetd/README.txt | 7 + apps/netutils/telnetd/shell.c | 139 ++++++++++++ apps/netutils/telnetd/shell.h | 97 +++++++++ apps/netutils/telnetd/telnetd.c | 459 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 796 insertions(+) create mode 100644 apps/netutils/telnetd/Makefile create mode 100644 apps/netutils/telnetd/README.txt create mode 100644 apps/netutils/telnetd/shell.c create mode 100644 apps/netutils/telnetd/shell.h create mode 100644 apps/netutils/telnetd/telnetd.c (limited to 'apps/netutils/telnetd') diff --git a/apps/netutils/telnetd/Makefile b/apps/netutils/telnetd/Makefile new file mode 100644 index 000000000..4c345d487 --- /dev/null +++ b/apps/netutils/telnetd/Makefile @@ -0,0 +1,94 @@ +############################################################################ +# apps/netutils/telnetd/Makefile +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 +# COPYRIGHT OWNER 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. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# Telnet daemon + +ASRCS = +CSRCS = + +ifeq ($(CONFIG_NET_TCP),y) +CSRCS += telnetd.c shell.c +endif + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = ../../libapps$(LIBEXT) + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + @( for obj in $(OBJS) ; do \ + $(call ARCHIVE, $@, $${obj}); \ + done ; ) + @touch .built + +.built: $(BIN) + +.depend: Makefile $(SRCS) + @$(MKDEP) $(ROOTDEPPATH) \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + @touch $@ + +# Register application +depend: .depend + +clean: + @rm -f $(BIN) *.o *~ .*.swp .built + $(call CLEAN) + +distclean: clean + @rm -f Make.dep .depend + +-include Make.dep diff --git a/apps/netutils/telnetd/README.txt b/apps/netutils/telnetd/README.txt new file mode 100644 index 000000000..24fcba7d5 --- /dev/null +++ b/apps/netutils/telnetd/README.txt @@ -0,0 +1,7 @@ +This directory is here for historical reasons. Nothing contained in this +directory is currently used by NuttX. This directly contains a functional +port of the tiny uIP shell. In the NuttX environment, the NuttShell (at +apps/nshlib) supercedes this tiny shell and also supports telnetd. + +This example is retained here for reference purposes only. + diff --git a/apps/netutils/telnetd/shell.c b/apps/netutils/telnetd/shell.c new file mode 100644 index 000000000..93fd11601 --- /dev/null +++ b/apps/netutils/telnetd/shell.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * netutils/telnetd/telnetd.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * Copyright (c) 2003, Adam Dunkels. + * 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "shell.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define SHELL_PROMPT "uIP 1.0> " + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct ptentry_s +{ + char *commandstr; + void (* pfunc)(void *handle, char *str); +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void parse(void *handle, register char *str, struct ptentry_s *t); +static void help(void *handle, char *str); +static void unknown(void *handle, char *str); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct ptentry_s g_parsetab[] = +{ + {"stats", help}, + {"conn", help}, + {"help", help}, + {"exit", shell_quit}, + {"?", help}, + {NULL, unknown} +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void parse(void *handle, char *str, struct ptentry_s *t) +{ + struct ptentry_s *p; + + for (p = t; p->commandstr != NULL; ++p) + { + if (strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) + { + break; + } + } + + p->pfunc(handle, str); +} + +static void help(void *handle, char *str) +{ + shell_output(handle, "Available commands:"); + shell_output(handle, "stats - show network statistics"); + shell_output(handle, "conn - show TCP connections"); + shell_output(handle, "help, ? - show help"); + shell_output(handle, "exit - exit shell"); +} + +static void unknown(void *handle, char *str) +{ + if (strlen(str) > 0) + { + shell_output(handle, "Unknown command: ", str); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void shell_init(void *handle) +{ +} + +void shell_start(void *handle) +{ + shell_output(handle, "uIP command shell"); + shell_output(handle, "Type '?' and return for help"); + shell_prompt(handle, SHELL_PROMPT); +} + +void shell_input(void *handle, char *cmd) +{ + parse(handle, cmd, g_parsetab); + shell_prompt(handle, SHELL_PROMPT); +} diff --git a/apps/netutils/telnetd/shell.h b/apps/netutils/telnetd/shell.h new file mode 100644 index 000000000..32325fe17 --- /dev/null +++ b/apps/netutils/telnetd/shell.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * netutils/telnetd/shell.h + * Interface for the Contiki shell. + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Based on uIP which also has a BSD style license: + * + * Author: Adam Dunkels + * Copyright (c) 2003, Adam Dunkels. + * 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + * + ****************************************************************************/ + +/* Some of the functions declared in this file must be implemented as + * a shell back-end in the architecture specific files of a Contiki + * port. + */ + +#ifndef __SHELL_H__ +#define __SHELL_H__ + +/* Initialize the shell. + * + * Called when the shell front-end process starts. This function may + * be used to start listening for signals. + */ + +void shell_init(void *handle); + +/* Start the shell back-end. + * + * Called by the front-end when a new shell is started. + */ + +void shell_start(void *handle); + +/* Process a shell command. + * + * This function will be called by the shell GUI / telnet server whan + * a command has been entered that should be processed by the shell + * back-end. + * + * command The command to be processed. + */ + +void shell_input(void *handle, char *command); + +/* Quit the shell. */ + +void shell_quit(void *handle, char *); + +/* Print a string to the shell window. + * + * This function is implemented by the shell GUI / telnet server and + * can be called by the shell back-end to output a string in the + * shell window. The string is automatically appended with a linebreak. + */ + +void shell_output(void *handle, const char *fmt, ...); + +/* Print a prompt to the shell window. + * + * This function can be used by the shell back-end to print out a + * prompt to the shell window. + * + */ + +void shell_prompt(void *handle, char *prompt); + +#endif /* __SHELL_H__ */ diff --git a/apps/netutils/telnetd/telnetd.c b/apps/netutils/telnetd/telnetd.c new file mode 100644 index 000000000..ccadd60dd --- /dev/null +++ b/apps/netutils/telnetd/telnetd.c @@ -0,0 +1,459 @@ +/**************************************************************************** + * netutils/telnetd/telnetd.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * This is a leverage of similar logic from uIP: + * + * Author: Adam Dunkels + * Copyright (c) 2003, Adam Dunkels. + * 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. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "shell.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define STATE_NORMAL 0 +#define STATE_IAC 1 +#define STATE_WILL 2 +#define STATE_WONT 3 +#define STATE_DO 4 +#define STATE_DONT 5 +#define STATE_CLOSE 6 + +#define TELNET_IAC 255 +#define TELNET_WILL 251 +#define TELNET_WONT 252 +#define TELNET_DO 253 +#define TELNET_DONT 254 + +/* Configurable settings */ + +#ifndef CONFIG_NETUTILS_IOBUFFER_SIZE +# define CONFIG_NETUTILS_IOBUFFER_SIZE 512 +#endif + +#ifndef CONFIG_NETUTILS_CMD_SIZE +# define CONFIG_NETUTILS_CMD_SIZE 40 +#endif + +/* As threads are created to handle each request, a stack must be allocated + * for the thread. Use a default if the user provided no stacksize. + */ + +#ifndef CONFIG_NETUTILS_TELNETDSTACKSIZE +# define CONFIG_NETUTILS_TELNETDSTACKSIZE 4096 +#endif + +/* Enabled dumping of all input/output buffers */ + +#undef CONFIG_NETUTILS_TELNETD_DUMPBUFFER + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct telnetd_s +{ + int tn_sockfd; + char tn_iobuffer[CONFIG_NETUTILS_IOBUFFER_SIZE]; + char tn_cmd[CONFIG_NETUTILS_CMD_SIZE]; + uint8_t tn_bufndx; + uint8_t tn_state; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: telnetd_dumpbuffer + * + * Description: + * Dump a buffer of data (debug only) + * + ****************************************************************************/ + +#ifdef CONFIG_NETUTILS_TELNETD_DUMPBUFFER +static inline void telnetd_dumpbuffer(FAR const char *msg, FAR const char *buffer, unsigned int nbytes) +{ + /* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_NET have to be + * defined or the following does nothing. + */ + + nvdbgdumpbuffer(msg, (FAR const uint8_t*)buffer, nbytes); +} +#else +# define telnetd_dumpbuffer(msg,buffer,nbytes) +#endif + +/**************************************************************************** + * Name: telnetd_putchar + * + * Description: + * Add another parsed character to the TELNET command string + * + ****************************************************************************/ + +static void telnetd_putchar(struct telnetd_s *pstate, uint8_t ch) +{ + /* Ignore carriage returns */ + + if (ch == ISO_cr) + { + return; + } + + /* Add all other characters to the cmd buffer */ + + pstate->tn_cmd[pstate->tn_bufndx] = ch; + + /* If a newline was added or if the buffer is full, then process it now */ + + if (ch == ISO_nl || pstate->tn_bufndx == (CONFIG_NETUTILS_CMD_SIZE - 1)) + { + if (pstate->tn_bufndx > 0) + { + pstate->tn_cmd[pstate->tn_bufndx] = '\0'; + } + + telnetd_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd)); + shell_input(pstate, pstate->tn_cmd); + pstate->tn_bufndx = 0; + } + else + { + pstate->tn_bufndx++; + vdbg("Add '%c', bufndx=%d\n", ch, pstate->tn_bufndx); + } +} + +/**************************************************************************** + * Name: telnetd_sendopt + * + * Description: + * + ****************************************************************************/ + +static void telnetd_sendopt(struct telnetd_s *pstate, uint8_t option, uint8_t value) +{ + uint8_t optbuf[4]; + optbuf[0] = TELNET_IAC; + optbuf[1] = option; + optbuf[2] = value; + optbuf[3] = 0; + + telnetd_dumpbuffer("Send optbuf", optbuf, 4); + if (send(pstate->tn_sockfd, optbuf, 4, 0) < 0) + { + dbg("[%d] Failed to send TELNET_IAC\n", pstate->tn_sockfd); + } +} + +/**************************************************************************** + * Name: telnetd_receive + * + * Description: + * Process a received TELENET buffer + * + ****************************************************************************/ + +static int telnetd_receive(struct telnetd_s *pstate, size_t len) +{ + char *ptr = pstate->tn_iobuffer; + uint8_t ch; + + while (len > 0) + { + ch = *ptr++; + len--; + + vdbg("ch=%02x state=%d\n", ch, pstate->tn_state); + switch (pstate->tn_state) + { + case STATE_IAC: + if (ch == TELNET_IAC) + { + telnetd_putchar(pstate, ch); + pstate->tn_state = STATE_NORMAL; + } + else + { + switch (ch) + { + case TELNET_WILL: + pstate->tn_state = STATE_WILL; + break; + + case TELNET_WONT: + pstate->tn_state = STATE_WONT; + break; + + case TELNET_DO: + pstate->tn_state = STATE_DO; + break; + + case TELNET_DONT: + pstate->tn_state = STATE_DONT; + break; + + default: + pstate->tn_state = STATE_NORMAL; + break; + } + } + break; + + case STATE_WILL: + /* Reply with a DONT */ + + telnetd_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_WONT: + /* Reply with a DONT */ + + telnetd_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_DO: + /* Reply with a WONT */ + + telnetd_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_DONT: + /* Reply with a WONT */ + + telnetd_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_NORMAL: + if (ch == TELNET_IAC) + { + pstate->tn_state = STATE_IAC; + } + else + { + telnetd_putchar(pstate, ch); + } + break; + } + } + return OK; +} + +/**************************************************************************** + * Name: telnetd_handler + * + * Description: + * Each time a new connection to port 23 is made, a new thread is created + * that begins at this entry point. There should be exactly one argument + * and it should be the socket descriptor (+1). + * + ****************************************************************************/ + +static void *telnetd_handler(void *arg) +{ + struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s)); + int sockfd = (int)arg; + int ret = ERROR; + + dbg("[%d] Started\n", sockfd); + + /* Verify that the state structure was successfully allocated */ + + if (pstate) + { + /* Initialize the thread state structure */ + + memset(pstate, 0, sizeof(struct telnetd_s)); + pstate->tn_sockfd = sockfd; + pstate->tn_state = STATE_NORMAL; + + /* Start up the shell */ + + shell_init(pstate); + shell_start(pstate); + + /* Loop processing each TELNET command */ + do + { + /* Read a buffer of data from the TELNET client */ + + ret = recv(pstate->tn_sockfd, pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, 0); + if (ret > 0) + { + + /* Process the received TELNET data */ + + telnetd_dumpbuffer("Received buffer", pstate->tn_iobuffer, ret); + ret = telnetd_receive(pstate, ret); + } + } + while (ret >= 0 && pstate->tn_state != STATE_CLOSE); + dbg("[%d] ret=%d tn_state=%d\n", sockfd, ret, pstate->tn_state); + + /* End of command processing -- Clean up and exit */ + + free(pstate); + } + + /* Exit the task */ + + dbg("[%d] Exitting\n", sockfd); + close(sockfd); + return NULL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: telnetd_init + * + * Description: + * This is the main processing thread for telnetd. It never returns + * unless an error occurs + * + ****************************************************************************/ + +void telnetd_init(void) +{ + /* Execute telnetd_handler on each connection to port 23 */ + + uip_server(HTONS(23), telnetd_handler, CONFIG_NETUTILS_TELNETDSTACKSIZE); +} + +/**************************************************************************** + * Name: shell_prompt + * + * Description: + * Print a prompt to the shell window. + * + * This function can be used by the shell back-end to print out a prompt + * to the shell window. + * + ****************************************************************************/ + +void shell_prompt(void *handle, char *str) +{ + struct telnetd_s *pstate = (struct telnetd_s *)handle; + int len = strlen(str); + + strncpy(pstate->tn_iobuffer, str, len); + telnetd_dumpbuffer("Shell prompt", pstate->tn_iobuffer, len); + if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len, 0) < 0) + { + dbg("[%d] Failed to send prompt\n", pstate->tn_sockfd); + } +} + +/**************************************************************************** + * Name: shell_output + * + * Description: + * Print a string to the shell window. + * + * This function is implemented by the shell GUI / telnet server and + * can be called by the shell back-end to output a string in the + * shell window. The string is automatically appended with a linebreak. + * + ****************************************************************************/ + +void shell_output(void *handle, const char *fmt, ...) +{ + struct telnetd_s *pstate = (struct telnetd_s *)handle; + unsigned len; + va_list ap; + + va_start(ap, fmt); + vsnprintf(pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, fmt, ap); + va_end(ap); + + len = strlen(pstate->tn_iobuffer); + if (len < CONFIG_NETUTILS_IOBUFFER_SIZE - 2) + { + pstate->tn_iobuffer[len] = ISO_cr; + pstate->tn_iobuffer[len+1] = ISO_nl; + pstate->tn_iobuffer[len+2] = '\0'; + } + + telnetd_dumpbuffer("Shell output", pstate->tn_iobuffer, len+2); + if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len+2, 0) < 0) + { + dbg("[%d] Failed to send response\n", pstate->tn_sockfd); + } +} + +/**************************************************************************** + * Name: shell_quit + * + * Description: + * Quit the shell + * + ****************************************************************************/ + +void shell_quit(void *handle, char *str) +{ + struct telnetd_s *pstate = (struct telnetd_s *)handle; + pstate->tn_state = STATE_CLOSE; +} + -- cgit v1.2.3