diff --git a/ChangeLog b/ChangeLog index 05b8b3f1ae..ab3d62c7a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -266,3 +266,4 @@ * Correct processing of input UDP broadcast packets. * Verfied basic DHCP client functionality (netutils/dhcpc) * Implemented send() timeout logic + * Add TELNETD front end to NSH (examples/nsh) diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index a0546ee630..b45fde8527 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -754,6 +754,7 @@ Other memory: * Correct processing of input UDP broadcast packets. * Verfied basic DHCP client functionality (netutils/dhcpc) * Implemented send() timeout logic + * Add TELNETD front end to NSH (examples/nsh) diff --git a/TODO b/TODO index a41b5f59d8..33bf5bab76 100644 --- a/TODO +++ b/TODO @@ -68,6 +68,7 @@ o Build system - Dependencies do not work correctly under configs//src (same as arch//src/board). o Applications & Tests +- Verify TELNET frontend to nsh o ARM - Add option to use a separate stack for interrupt handling. At present, @@ -75,6 +76,7 @@ o ARM user stack allocation larger than needed. o ARM/C5471 +- Needs an Ethernet driver o ARM/DM320 - It seems that when a lot of debug statements are added, the system no diff --git a/arch/arm/src/common/up_head.S b/arch/arm/src/common/up_head.S index 65403ee237..e6afed640d 100644 --- a/arch/arm/src/common/up_head.S +++ b/arch/arm/src/common/up_head.S @@ -284,7 +284,7 @@ __start: #endif /* Perform early serial initialization */ -#ifdef CONFIG_DEV_CONSOLE +#if defined(CONFIG_DEV_CONSOLE) && CONFIG_NFILE_DESCRIPTORS > 0 bl up_earlyserialinit #endif diff --git a/arch/arm/src/common/up_nommuhead.S b/arch/arm/src/common/up_nommuhead.S index 9d10449a7d..581ed0a6d2 100644 --- a/arch/arm/src/common/up_nommuhead.S +++ b/arch/arm/src/common/up_nommuhead.S @@ -104,10 +104,13 @@ __start: blt 1b #endif + +#if defined(CONFIG_DEV_CONSOLE) && CONFIG_NFILE_DESCRIPTORS >0 /* Perform early serial initialization */ mov fp, #0 bl up_earlyserialinit +#endif #ifdef CONFIG_DEBUG mov r0, #'C' diff --git a/configs/c5471evm/defconfig b/configs/c5471evm/defconfig index 2a567f13bc..0385d44f31 100644 --- a/configs/c5471evm/defconfig +++ b/configs/c5471evm/defconfig @@ -299,6 +299,18 @@ CONFIG_NET_BROADCAST=n CONFIG_NET_DHCP_LIGHT=n CONFIG_NET_RESOLV_ENTRIES=4 +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # Stack and heap information # diff --git a/configs/m68332evb/defconfig b/configs/m68332evb/defconfig index f909f455d1..ce4bed812e 100644 --- a/configs/m68332evb/defconfig +++ b/configs/m68332evb/defconfig @@ -288,6 +288,18 @@ CONFIG_NET_BROADCAST=n CONFIG_NET_DHCP_LIGHT=n CONFIG_NET_RESOLV_ENTRIES=4 +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # Stack and heap information # diff --git a/configs/mcu123-lpc214x/defconfig b/configs/mcu123-lpc214x/defconfig index 5af107ef5d..6401217c80 100644 --- a/configs/mcu123-lpc214x/defconfig +++ b/configs/mcu123-lpc214x/defconfig @@ -312,6 +312,18 @@ CONFIG_NET_BROADCAST=n CONFIG_NET_DHCP_LIGHT=n CONFIG_NET_RESOLV_ENTRIES=4 +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # Stack and heap information # diff --git a/configs/ntosd-dm320/defconfig b/configs/ntosd-dm320/defconfig index b8ecb377dd..ed953d6bae 100644 --- a/configs/ntosd-dm320/defconfig +++ b/configs/ntosd-dm320/defconfig @@ -317,6 +317,18 @@ CONFIG_EXAMPLE_NETTEST_DRIPADDR=(10<<24|0<<16|0<<8|1) CONFIG_EXAMPLE_NETTEST_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_NETTEST_CLIENTIP=(10<<24|0<<16|0<<8|1) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # DM90x0 Driver Settings CONFIG_NET_DM90x0=n diff --git a/configs/ntosd-dm320/netconfig b/configs/ntosd-dm320/netconfig index 70d43c30c4..9ae97b658f 100644 --- a/configs/ntosd-dm320/netconfig +++ b/configs/ntosd-dm320/netconfig @@ -317,6 +317,18 @@ CONFIG_EXAMPLE_NETTEST_DRIPADDR=(10<<24|0<<16|0<<8|1) CONFIG_EXAMPLE_NETTEST_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_NETTEST_CLIENTIP=(10<<24|0<<16|0<<8|1) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # DM90x0 Driver Settings CONFIG_NET_DM90x0=y diff --git a/configs/ntosd-dm320/udpconfig b/configs/ntosd-dm320/udpconfig index b8216ee5e8..cece23cd52 100644 --- a/configs/ntosd-dm320/udpconfig +++ b/configs/ntosd-dm320/udpconfig @@ -325,6 +325,18 @@ CONFIG_EXAMPLE_UDP_DRIPADDR=(10<<24|0<<16|0<<8|1) CONFIG_EXAMPLE_UDP_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_UDP_SERVERIP=(10<<24|0<<16|0<<8|1) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # DM90x0 Driver Settings CONFIG_NET_DM90x0=y diff --git a/configs/ntosd-dm320/uipconfig b/configs/ntosd-dm320/uipconfig index b66546b388..6f06d089fa 100644 --- a/configs/ntosd-dm320/uipconfig +++ b/configs/ntosd-dm320/uipconfig @@ -317,6 +317,18 @@ CONFIG_EXAMPLE_NETTEST_DRIPADDR=(10<<24|0<<16|0<<8|1) CONFIG_EXAMPLE_NETTEST_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_NETTEST_CLIENTIP=(10<<24|0<<16|0<<8|1) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # DM90x0 Driver Settings CONFIG_NET_DM90x0=y diff --git a/configs/pjrc-8051/defconfig b/configs/pjrc-8051/defconfig index 4714590eea..fd2965129f 100644 --- a/configs/pjrc-8051/defconfig +++ b/configs/pjrc-8051/defconfig @@ -285,6 +285,18 @@ CONFIG_NET_BROADCAST=n CONFIG_NET_DHCP_LIGHT=n CONFIG_NET_RESOLV_ENTRIES=4 +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # Stack and heap information # diff --git a/configs/sim/defconfig b/configs/sim/defconfig index 6107a781e4..5378a513ba 100644 --- a/configs/sim/defconfig +++ b/configs/sim/defconfig @@ -279,6 +279,18 @@ CONFIG_EXAMPLE_NETTEST_DRIPADDR=(192<<24|168<<16|0<<8|1) CONFIG_EXAMPLE_NETTEST_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_NETTEST_CLIENTIP=(192<<24|168<<16|0<<8|106) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # # Stack and heap information # diff --git a/configs/sim/netconfig b/configs/sim/netconfig index 002502356b..ae3a70f161 100644 --- a/configs/sim/netconfig +++ b/configs/sim/netconfig @@ -280,6 +280,18 @@ CONFIG_EXAMPLE_NETTEST_DRIPADDR=(192<<24|168<<16|0<<8|1) CONFIG_EXAMPLE_NETTEST_NETMASK=(255<<24|255<<16|255<<8|0) CONFIG_EXAMPLE_NETTEST_CLIENTIP=(192<<24|168<<16|0<<8|106) +# +# Settings for examples/nsh +CONFIG_EXAMPLES_NSH_TELNET=n +CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE=512 +CONFIG_EXAMPLES_NSH_CMD_SIZE=40 +CONFIG_EXAMPLES_NSH_STACKSIZE=4096 +CONFIG_EXAMPLES_NSH_DHCPC=n +CONFIG_EXAMPLES_NSH_NOMAC=n +CONFIG_EXAMPLES_NSH_IPADDR=(10<<24|0<<16|0<<8|2) +CONFIG_EXAMPLES_NSH_DRIPADDR=(10<<24|0<<16|0<<8|1) +CONFIG_EXAMPLES_NSH_NETMASK=(255<<24|255<<16|255<<8|0) + # Stack and heap information # # CONFIG_BOOT_FROM_FLASH - Some configurations support XIP diff --git a/examples/nsh/Makefile b/examples/nsh/Makefile index faeb30246b..ef812a00db 100644 --- a/examples/nsh/Makefile +++ b/examples/nsh/Makefile @@ -1,5 +1,5 @@ -############################################################ -# Makefile +############################################################################ +# examples/nsh/Makefile # # Copyright (C) 2007 Gregory Nutt. All rights reserved. # Author: Gregory Nutt @@ -31,7 +31,7 @@ # 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 @@ -39,8 +39,15 @@ MKDEP = $(TOPDIR)/tools/mkdeps.sh ASRCS = -AOBJS = $(ASRCS:.S=$(OBJEXT)) CSRCS = nsh_main.c nsh_fscmds.c nsh_proccmds.c nsh_envcmds.c + +ifeq ($(CONFIG_EXAMPLES_NSH_TELNET),y) +CSRCS += nsh_telnetd.c +else +CSRCS += nsh_serial.c +endif + +AOBJS = $(ASRCS:.S=$(OBJEXT)) COBJS = $(CSRCS:.c=$(OBJEXT)) SRCS = $(ASRCS) $(CSRCS) diff --git a/examples/nsh/nsh.h b/examples/nsh/nsh.h index fc9f807d2c..7d0179b8e0 100644 --- a/examples/nsh/nsh.h +++ b/examples/nsh/nsh.h @@ -41,23 +41,30 @@ ****************************************************************************/ #include +#ifdef CONFIG_EXAMPLES_NSH_TELNET +#else +# include +#endif /**************************************************************************** * Definitions ****************************************************************************/ +#define NSH_MAX_ARGUMENTS 6 + #define errno (*get_errno_ptr()) /**************************************************************************** * Public Types ****************************************************************************/ -typedef void (*cmd_t)(int argc, char **argv); +typedef void (*cmd_t)(FAR void *handle, int argc, char **argv); /**************************************************************************** * Public Data ****************************************************************************/ +extern const char g_nshprompt[]; extern const char g_fmtargrequired[]; extern const char g_fmtarginvalid[]; extern const char g_fmtcmdnotfound[]; @@ -71,30 +78,56 @@ extern const char g_fmtcmdoutofmemory[]; * Public Function Prototypes ****************************************************************************/ -#if CONFIG_NFILE_DESCRIPTORS > 0 -extern void cmd_cat(int argc, char **argv); -extern void cmd_cp(int argc, char **argv); +/* Message handler */ + +extern int nsh_parse(FAR void *handle, char *cmdline); + +/* I/O interfaces */ + +#ifdef CONFIG_EXAMPLES_NSH_TELNET + +extern int nsh_telnetmain(void); +extern int nsh_telnetout(FAR void *handle, const char *fmt, ...); + +# define nsh_main() nsh_telnetmain() +# define nsh_output(handle, ...) nsh_telnetout(handle, __VA_ARGS__) + +#else + +extern int nsh_serialmain(void); + +# define nsh_main() nsh_serialmain() +# define nsh_output(handle, ...) printf(__VA_ARGS__) + #endif -extern void cmd_echo(int argc, char **argv); -extern void cmd_exec(int argc, char **argv); + +/* Shell command handlers */ + #if CONFIG_NFILE_DESCRIPTORS > 0 -extern void cmd_ls(int argc, char **argv); +extern void cmd_cat(FAR void *handle, int argc, char **argv); +extern void cmd_cp(FAR void *handle, int argc, char **argv); +#endif +extern void cmd_echo(FAR void *handle, int argc, char **argv); +extern void cmd_exec(FAR void *handle, int argc, char **argv); +extern void cmd_exit(FAR void *handle, int argc, char **argv); +#if CONFIG_NFILE_DESCRIPTORS > 0 +extern void cmd_ls(FAR void *handle, int argc, char **argv); #endif #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -extern void cmd_mkdir(int argc, char **argv); -extern void cmd_mount(int argc, char **argv); +extern void cmd_mkdir(FAR void *handle, int argc, char **argv); +extern void cmd_mount(FAR void *handle, int argc, char **argv); #endif -extern void cmd_ps(int argc, char **argv); +extern void cmd_ps(FAR void *handle, int argc, char **argv); #ifndef CONFIG_DISABLE_ENVIRON -extern void cmd_set(int argc, char **argv); +extern void cmd_set(FAR void *handle, int argc, char **argv); #endif #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -extern void cmd_rm(int argc, char **argv); -extern void cmd_rmdir(int argc, char **argv); -extern void cmd_umount(int argc, char **argv); +extern void cmd_rm(FAR void *handle, int argc, char **argv); +extern void cmd_rmdir(FAR void *handle, int argc, char **argv); +extern void cmd_umount(FAR void *handle, int argc, char **argv); #endif #ifndef CONFIG_DISABLE_ENVIRON -extern void cmd_unset(int argc, char **argv); +extern void cmd_unset(FAR void *handle, int argc, char **argv); #endif #endif /* __NSH_H */ diff --git a/examples/nsh/nsh_envcmds.c b/examples/nsh/nsh_envcmds.c index c6ff9a0f29..4af3d026d8 100644 --- a/examples/nsh/nsh_envcmds.c +++ b/examples/nsh/nsh_envcmds.c @@ -79,7 +79,7 @@ * Name: cmd_echo ****************************************************************************/ -void cmd_echo(int argc, char **argv) +void cmd_echo(FAR void *handle, int argc, char **argv) { int i; @@ -97,16 +97,16 @@ void cmd_echo(int argc, char **argv) char *value = getenv(argv[i]+1); if (value) { - printf("%s ", value); + nsh_output(handle, "%s ", value); } } else #endif { - printf("%s ", argv[i]); + nsh_output(handle, "%s ", argv[i]); } } - putchar('\n'); + nsh_output(handle, "\n"); } /**************************************************************************** @@ -114,11 +114,11 @@ void cmd_echo(int argc, char **argv) ****************************************************************************/ #ifndef CONFIG_DISABLE_ENVIRON -void cmd_set(int argc, char **argv) +void cmd_set(FAR void *handle, int argc, char **argv) { if (setenv(argv[1], argv[2], TRUE) < 0) { - printf(g_fmtcmdfailed, argv[0], "setenv", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "setenv", strerror(errno)); } } #endif @@ -128,11 +128,11 @@ void cmd_set(int argc, char **argv) ****************************************************************************/ #ifndef CONFIG_DISABLE_ENVIRON -void cmd_unset(int argc, char **argv) +void cmd_unset(FAR void *handle, int argc, char **argv) { if (unsetenv(argv[1]) < 0) { - printf(g_fmtcmdfailed, argv[0], "unsetenv", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "unsetenv", strerror(errno)); } } #endif diff --git a/examples/nsh/nsh_fscmds.c b/examples/nsh/nsh_fscmds.c index a40120d8f5..6f7a38a503 100644 --- a/examples/nsh/nsh_fscmds.c +++ b/examples/nsh/nsh_fscmds.c @@ -90,7 +90,7 @@ * Private Types ****************************************************************************/ -typedef int (*direntry_handler_t)(const char *, struct dirent *, void *); +typedef int (*direntry_handler_t)(FAR void *, const char *, struct dirent *, void *); /**************************************************************************** * Private Function Prototypes @@ -151,7 +151,8 @@ static char *getdirpath(const char *path, const char *file) * Name: foreach_direntry ****************************************************************************/ -static int foreach_direntry(const char *cmd, const char *dirpath, +#if CONFIG_NFILE_DESCRIPTORS > 0 +static int foreach_direntry(FAR void *handle, const char *cmd, const char *dirpath, direntry_handler_t handler, void *pvarg) { DIR *dirp; @@ -171,7 +172,7 @@ static int foreach_direntry(const char *cmd, const char *dirpath, { /* Failed to open the directory */ - printf(g_fmtnosuch, cmd, "directory", dirpath); + nsh_output(handle, g_fmtnosuch, cmd, "directory", dirpath); return ERROR; } @@ -189,7 +190,7 @@ static int foreach_direntry(const char *cmd, const char *dirpath, /* Call the handler with this directory entry */ - if (handler(dirpath, entryp, pvarg) < 0) + if (handler(handle, dirpath, entryp, pvarg) < 0) { /* The handler reported a problem */ @@ -201,13 +202,14 @@ static int foreach_direntry(const char *cmd, const char *dirpath, closedir(dirp); return ret; } +#endif /**************************************************************************** * Name: ls_handler ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -static int ls_handler(const char *dirpath, struct dirent *entryp, void *pvarg) +static int ls_handler(FAR void *handle, const char *dirpath, struct dirent *entryp, void *pvarg) { unsigned int lsflags = (unsigned int)pvarg; int ret; @@ -225,7 +227,7 @@ static int ls_handler(const char *dirpath, struct dirent *entryp, void *pvarg) free(fullpath); if (ret != 0) { - printf(g_fmtcmdfailed, "ls", "stat", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, "ls", "stat", strerror(errno)); return OK; } @@ -290,30 +292,30 @@ static int ls_handler(const char *dirpath, struct dirent *entryp, void *pvarg) details[9]='x'; } - printf(" %s", details); + nsh_output(handle, " %s", details); } if ((lsflags & LSFLAGS_SIZE) != 0) { - printf("%8d", buf.st_size); + nsh_output(handle, "%8d", buf.st_size); } } /* then provide the filename that is common to normal and verbose output */ #ifdef CONFIG_FULL_PATH - printf(" %s/%s", arg, entryp->d_name); + nsh_output(handle, " %s/%s", arg, entryp->d_name); #else - printf(" %s", entryp->d_name); + nsh_output(handle, " %s", entryp->d_name); #endif if (DIRENT_ISDIRECTORY(entryp->d_type)) { - printf("/\n"); + nsh_output(handle, "/\n"); } else { - putchar('\n'); + nsh_output(handle, "\n"); } return OK; } @@ -324,7 +326,7 @@ static int ls_handler(const char *dirpath, struct dirent *entryp, void *pvarg) ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -static int ls_recursive(const char *dirpath, struct dirent *entryp, void *pvarg) +static int ls_recursive(FAR void *handle, const char *dirpath, struct dirent *entryp, void *pvarg) { /* Is this entry a directory? */ @@ -337,12 +339,12 @@ static int ls_recursive(const char *dirpath, struct dirent *entryp, void *pvarg) /* List the directory contents */ - printf("%s:\n", newpath); - foreach_direntry("ls", newpath, ls_handler, pvarg); + nsh_output(handle, "%s:\n", newpath); + foreach_direntry(handle, "ls", newpath, ls_handler, pvarg); /* Then recurse to list each directory within the directory */ - foreach_direntry("ls", newpath, ls_recursive, pvarg); + foreach_direntry(handle, "ls", newpath, ls_recursive, pvarg); free(newpath); } return OK; @@ -358,7 +360,7 @@ static int ls_recursive(const char *dirpath, struct dirent *entryp, void *pvarg) ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_cat(int argc, char **argv) +void cmd_cat(FAR void *handle, int argc, char **argv) { char buffer[1024]; @@ -367,7 +369,7 @@ void cmd_cat(int argc, char **argv) int fd = open(argv[1], O_RDONLY); if (fd < 0) { - printf(g_fmtcmdfailed, argv[0], "open", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "open", strerror(errno)); return; } @@ -385,7 +387,7 @@ void cmd_cat(int argc, char **argv) if (errno != EINTR) { - printf(g_fmtcmdfailed, argv[0], "read", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "read", strerror(errno)); break; } } @@ -405,7 +407,7 @@ void cmd_cat(int argc, char **argv) if (errno != EINTR) { - printf(g_fmtcmdfailed, argv[0], "write", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "write", strerror(errno)); break; } } @@ -433,7 +435,7 @@ void cmd_cat(int argc, char **argv) ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_cp(int argc, char **argv) +void cmd_cp(FAR void *handle, int argc, char **argv) { struct stat buf; char *fullpath = NULL; @@ -448,7 +450,7 @@ void cmd_cp(int argc, char **argv) rdfd = open(argv[1], O_RDONLY); if (rdfd < 0) { - printf(g_fmtcmdfailed, argv[0], "open", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "open", strerror(errno)); return; } @@ -470,7 +472,7 @@ void cmd_cp(int argc, char **argv) fullpath = getdirpath(argv[2], basename(argv[1]) ); if (!fullpath) { - printf(g_fmtcmdoutofmemory, argv[0]); + nsh_output(handle, g_fmtcmdoutofmemory, argv[0]); goto out_with_rdfd; } @@ -490,7 +492,7 @@ void cmd_cp(int argc, char **argv) wrfd = open(wrpath, oflags, 0666); if (wrfd < 0) { - printf(g_fmtcmdfailed, argv[0], "open", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "open", strerror(errno)); goto out_with_fullpath; } @@ -514,7 +516,7 @@ void cmd_cp(int argc, char **argv) { /* Read error */ - printf(g_fmtcmdfailed, argv[0], "read", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "read", strerror(errno)); goto out_with_wrfd; } } @@ -531,7 +533,7 @@ void cmd_cp(int argc, char **argv) { /* Read error */ - printf(g_fmtcmdfailed, argv[0], "write", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "write", strerror(errno)); goto out_with_wrfd; } } @@ -557,7 +559,7 @@ out_with_rdfd: ****************************************************************************/ #if CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_ls(int argc, char **argv) +void cmd_ls(FAR void *handle, int argc, char **argv) { unsigned int lsflags = 0; int ret; @@ -583,7 +585,7 @@ void cmd_ls(int argc, char **argv) case '?': default: - printf(g_fmtarginvalid, argv[0]); + nsh_output(handle, g_fmtarginvalid, argv[0]); return; } } @@ -592,24 +594,24 @@ void cmd_ls(int argc, char **argv) if (optind + 1 < argc) { - printf(g_fmttoomanyargs, argv[0]); + nsh_output(handle, g_fmttoomanyargs, argv[0]); return; } else if (optind + 1 > argc) { - printf(g_fmtargrequired, argv[0]); + nsh_output(handle, g_fmtargrequired, argv[0]); return; } /* List the directory contents */ - printf("%s:\n", argv[optind]); - ret = foreach_direntry("ls", argv[optind], ls_handler, (void*)lsflags); + nsh_output(handle, "%s:\n", argv[optind]); + ret = foreach_direntry(handle, "ls", argv[optind], ls_handler, (void*)lsflags); if (ret == OK && (lsflags & LSFLAGS_RECURSIVE) != 0) { /* Then recurse to list each directory within the directory */ - ret = foreach_direntry("ls", argv[optind], ls_recursive, (void*)lsflags); + ret = foreach_direntry(handle, "ls", argv[optind], ls_recursive, (void*)lsflags); } } #endif @@ -619,12 +621,12 @@ void cmd_ls(int argc, char **argv) ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_mkdir(int argc, char **argv) +void cmd_mkdir(FAR void *handle, int argc, char **argv) { int result = mkdir(argv[1], 0777); if ( result < 0) { - printf(g_fmtcmdfailed, argv[0], "mkdir", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "mkdir", strerror(errno)); } } #endif @@ -634,7 +636,7 @@ void cmd_mkdir(int argc, char **argv) ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_mount(int argc, char **argv) +void cmd_mount(FAR void *handle, int argc, char **argv) { char *filesystem = 0; int result; @@ -651,12 +653,12 @@ void cmd_mount(int argc, char **argv) break; case ':': - printf(g_fmtargrequired, argv[0]); + nsh_output(handle, g_fmtargrequired, argv[0]); return; case '?': default: - printf(g_fmtarginvalid, argv[0]); + nsh_output(handle, g_fmtarginvalid, argv[0]); return; } } @@ -665,12 +667,12 @@ void cmd_mount(int argc, char **argv) if (optind + 2 < argc) { - printf(g_fmttoomanyargs, argv[0]); + nsh_output(handle, g_fmttoomanyargs, argv[0]); return; } else if (optind + 2 > argc) { - printf(g_fmtargrequired, argv[0]); + nsh_output(handle, g_fmtargrequired, argv[0]); return; } @@ -678,7 +680,7 @@ void cmd_mount(int argc, char **argv) result = mount(argv[optind], argv[optind+1], filesystem, 0, NULL); if ( result < 0) { - printf(g_fmtcmdfailed, argv[0], "mount", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "mount", strerror(errno)); } } #endif @@ -688,11 +690,11 @@ void cmd_mount(int argc, char **argv) ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_rm(int argc, char **argv) +void cmd_rm(FAR void *handle, int argc, char **argv) { if (unlink(argv[1]) < 0) { - printf(g_fmtcmdfailed, argv[0], "unlink", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "unlink", strerror(errno)); } } #endif @@ -702,11 +704,11 @@ void cmd_rm(int argc, char **argv) ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_rmdir(int argc, char **argv) +void cmd_rmdir(FAR void *handle, int argc, char **argv) { if (rmdir(argv[1]) < 0) { - printf(g_fmtcmdfailed, argv[0], "rmdir", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "rmdir", strerror(errno)); } } #endif @@ -716,13 +718,13 @@ void cmd_rmdir(int argc, char **argv) ****************************************************************************/ #if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 -void cmd_umount(int argc, char **argv) +void cmd_umount(FAR void *handle, int argc, char **argv) { /* Perform the umount */ int result = umount(argv[1]); if ( result < 0) { - printf(g_fmtcmdfailed, argv[0], "umount", strerror(errno)); + nsh_output(handle, g_fmtcmdfailed, argv[0], "umount", strerror(errno)); } } #endif diff --git a/examples/nsh/nsh_main.c b/examples/nsh/nsh_main.c index a52d2d0b8e..cb65833d1d 100644 --- a/examples/nsh/nsh_main.c +++ b/examples/nsh/nsh_main.c @@ -51,7 +51,6 @@ #define CONFIG_NSH_LINE_SIZE 80 #undef CONFIG_FULL_PATH -#define NSH_MAX_ARGUMENTS 6 /**************************************************************************** * Private Types @@ -70,14 +69,13 @@ struct cmdmap_s * Private Function Prototypes ****************************************************************************/ -static void cmd_help(int argc, char **argv); -static void cmd_unrecognized(int argc, char **argv); +static void cmd_help(FAR void *handle, int argc, char **argv); +static void cmd_unrecognized(FAR void *handle, int argc, char **argv); /**************************************************************************** * Private Data ****************************************************************************/ -static char line[CONFIG_NSH_LINE_SIZE]; static const char delim[] = " \t\n"; static const struct cmdmap_s g_cmdmap[] = @@ -92,6 +90,7 @@ static const struct cmdmap_s g_cmdmap[] = { "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[ [...]]" }, #endif { "exec", cmd_exec, 2, 3, "" }, + { "exit", cmd_exit, 1, 1, NULL }, { "help", cmd_help, 1, 1, NULL }, #if CONFIG_NFILE_DESCRIPTORS > 0 { "ls", cmd_ls, 2, 5, "[-lRs] " }, @@ -119,6 +118,7 @@ static const struct cmdmap_s g_cmdmap[] = * Public Data ****************************************************************************/ +const char g_nshprompt[] = "nsh> "; const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n"; const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n"; const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n"; @@ -136,20 +136,20 @@ const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n"; * Name: cmd_help ****************************************************************************/ -static void cmd_help(int argc, char **argv) +static void cmd_help(FAR void *handle, int argc, char **argv) { const struct cmdmap_s *ptr; - printf("NSH commands:\n"); + nsh_output(handle, "NSH commands:\n"); for (ptr = g_cmdmap; ptr->cmd; ptr++) { if (ptr->usage) { - printf(" %s %s\n", ptr->cmd, ptr->usage); + nsh_output(handle, " %s %s\n", ptr->cmd, ptr->usage); } else { - printf(" %s\n", ptr->cmd); + nsh_output(handle, " %s\n", ptr->cmd); } } } @@ -158,9 +158,9 @@ static void cmd_help(int argc, char **argv) * Name: cmd_unrecognized ****************************************************************************/ -static void cmd_unrecognized(int argc, char **argv) +static void cmd_unrecognized(FAR void *handle, int argc, char **argv) { - printf(g_fmtcmdnotfound, argv[0]); + nsh_output(handle, g_fmtcmdnotfound, argv[0]); } /**************************************************************************** @@ -182,94 +182,86 @@ void user_initialize(void) int user_start(int argc, char *argv[]) { - printf("NuttShell (NSH)\n"); - fflush(stdout); + return nsh_main(); +} - for (;;) +/**************************************************************************** + * Name: nsh_parse + ****************************************************************************/ + +int nsh_parse(FAR void *handle, char *cmdline) +{ + const struct cmdmap_s *cmdmap; + char *argv[NSH_MAX_ARGUMENTS+1]; + char *saveptr; + char *cmd; + int argc; + + /* Parse out the command at the beginning of the line */ + + cmd = strtok_r(cmdline, " \t\n", &saveptr); + if (cmd) { - const struct cmdmap_s *cmdmap; - char *saveptr; - char *cmd; + cmd_t handler = cmd_unrecognized; - /* Get the next line of input */ + /* Parse all of the arguments following the command name */ - fgets(line, CONFIG_NSH_LINE_SIZE, stdin); - /* Parse out the command at the beginning of the line */ - - cmd = strtok_r(line, " \t\n", &saveptr); - if (cmd) + argv[0] = cmd; + for (argc = 1; argc < NSH_MAX_ARGUMENTS+1; argc++) { - cmd_t handler = cmd_unrecognized; - - /* Parse all of the arguments following the command name */ - - char *cmd_argv[NSH_MAX_ARGUMENTS+1]; - int cmd_argc; - - cmd_argv[0] = cmd; - for (cmd_argc = 1; cmd_argc < NSH_MAX_ARGUMENTS+1; cmd_argc++) + argv[argc] = strtok_r( NULL, " \t\n", &saveptr); + if (!argv[argc]) { - cmd_argv[cmd_argc] = strtok_r( NULL, " \t\n", &saveptr); - if ( !cmd_argv[cmd_argc] ) - { - break; - } + break; } + } - if (cmd_argc > NSH_MAX_ARGUMENTS) + if (argc > NSH_MAX_ARGUMENTS) + { + nsh_output(handle, g_fmttoomanyargs, cmd); + } + + /* See if the command is one that we understand */ + + for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++) + { + if (strcmp(cmdmap->cmd, cmd) == 0) { - printf(g_fmttoomanyargs, cmd); - } - - /* See if the command is one that we understand */ - - for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++) - { - if (strcmp(cmdmap->cmd, cmd) == 0) - { - /* Check if a valid number of arguments was provided. We + /* Check if a valid number of arguments was provided. We * do this simple, imperfect checking here so that it does * not have to be performed in each command. */ - if (cmd_argc < cmdmap->minargs) - { - /* Fewer than the minimum number were provided */ + if (argc < cmdmap->minargs) + { + /* Fewer than the minimum number were provided */ - printf(g_fmtargrequired, cmd); - handler = NULL; - break; - } - else if (cmd_argc > cmdmap->maxargs) - { - /* More than the maximum number were provided */ + nsh_output(handle, g_fmtargrequired, cmd); + return ERROR; + } + else if (argc > cmdmap->maxargs) + { + /* More than the maximum number were provided */ - printf(g_fmttoomanyargs, cmd); - handler = NULL; - break; - } - else - { - /* A valid number of arguments were provided (this does - * not mean they are right. - */ + nsh_output(handle, g_fmttoomanyargs, cmd); + return ERROR; + } + else + { + /* A valid number of arguments were provided (this does + * not mean they are right). + */ - handler = cmdmap->handler; - break; - } + handler = cmdmap->handler; + break; } } - - /* If a error was detected above, handler will be nullified to - * prevent reporting multiple errors. - */ - - if (handler) - { - handler(cmd_argc, cmd_argv); - } } - fflush(stdout); + + handler(handle, argc, argv); + return OK; } + + return ERROR; } diff --git a/examples/nsh/nsh_proccmds.c b/examples/nsh/nsh_proccmds.c index 285db55863..70a5add0ca 100644 --- a/examples/nsh/nsh_proccmds.c +++ b/examples/nsh/nsh_proccmds.c @@ -97,27 +97,27 @@ static void ps_task(FAR _TCB *tcb, FAR void *arg) { boolean needcomma = FALSE; int i; - printf("%5d %3d %4s %7s%c%c %8s ", - tcb->pid, tcb->sched_priority, - tcb->flags & TCB_FLAG_ROUND_ROBIN ? "RR " : "FIFO", - tcb->flags & TCB_FLAG_PTHREAD ? "PTHREAD" : "TASK ", - tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : ' ', - tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : ' ', - g_statenames[tcb->task_state]); + nsh_output(arg, "%5d %3d %4s %7s%c%c %8s ", + tcb->pid, tcb->sched_priority, + tcb->flags & TCB_FLAG_ROUND_ROBIN ? "RR " : "FIFO", + tcb->flags & TCB_FLAG_PTHREAD ? "PTHREAD" : "TASK ", + tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : ' ', + tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : ' ', + g_statenames[tcb->task_state]); - printf("%s(", tcb->argv[0]); + nsh_output(arg, "%s(", tcb->argv[0]); for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && tcb->argv[i]; i++) { if (needcomma) { - printf(", %p", tcb->argv[i]); + nsh_output(arg, ", %p", tcb->argv[i]); } else { - printf("%p", tcb->argv[i]); + nsh_output(arg, "%p", tcb->argv[i]); } } - printf(")\n"); + nsh_output(arg, ")\n"); } /**************************************************************************** @@ -128,7 +128,7 @@ static void ps_task(FAR _TCB *tcb, FAR void *arg) * Name: cmd_exec ****************************************************************************/ -void cmd_exec(int argc, char **argv) +void cmd_exec(FAR void *handle, int argc, char **argv) { char *endptr; long addr; @@ -136,11 +136,11 @@ void cmd_exec(int argc, char **argv) addr = strtol(argv[1], &endptr, 0); if (!addr || endptr == argv[1] || *endptr != '\0') { - printf(g_fmtarginvalid, argv[0]); + nsh_output(handle, g_fmtarginvalid, argv[0]); return; } - printf("Calling %p\n", (exec_t)addr); + nsh_output(handle, "Calling %p\n", (exec_t)addr); ((exec_t)addr)(); } @@ -148,8 +148,8 @@ void cmd_exec(int argc, char **argv) * Name: cmd_ps ****************************************************************************/ -void cmd_ps(int argc, char **argv) +void cmd_ps(FAR void *handle, int argc, char **argv) { - printf("PID PRI SCHD TYPE NP STATE NAME\n"); - sched_foreach(ps_task, NULL); + nsh_output(handle, "PID PRI SCHD TYPE NP STATE NAME\n"); + sched_foreach(ps_task, handle); } diff --git a/examples/nsh/nsh_serial.c b/examples/nsh/nsh_serial.c new file mode 100644 index 0000000000..7716521abd --- /dev/null +++ b/examples/nsh/nsh_serial.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * examples/nsh/nsh_serial.h + * + * Copyright (C) 2007 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 Gregory Nutt 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "nsh.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define CONFIG_NSH_LINE_SIZE 80 +#undef CONFIG_FULL_PATH + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct cmdmap_s +{ + const char *cmd; /* Name of the command */ + cmd_t handler; /* Function that handles the command */ + ubyte minargs; /* Minimum number of arguments (including command) */ + ubyte maxargs; /* Maximum number of arguments (including command) */ + const char *usage; /* Usage instructions for 'help' command */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static char line[CONFIG_NSH_LINE_SIZE]; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_main + ****************************************************************************/ + +int nsh_serialmain(void) +{ + printf("NuttShell (NSH)\n"); + fflush(stdout); + + for (;;) + { + /* Display the prompt string */ + + fputs(g_nshprompt, stdout); + fflush(stdout); + + /* Get the next line of input */ + + fgets(line, CONFIG_NSH_LINE_SIZE, stdin); + + /* Parse process the command */ + + (void)nsh_parse(NULL, line); + fflush(stdout); + } +} + +/**************************************************************************** + * Name: cmd_exit + * + * Description: + * Exit the shell task + * + ****************************************************************************/ + +void cmd_exit(void *handle, int argc, char **argv) +{ + exit(0); +} diff --git a/examples/nsh/nsh_telnetd.c b/examples/nsh/nsh_telnetd.c new file mode 100644 index 0000000000..f90f535bac --- /dev/null +++ b/examples/nsh/nsh_telnetd.c @@ -0,0 +1,565 @@ +/**************************************************************************** + * examples/nsh/nsh_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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "nsh.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_EXAMPLES_NSH_IOBUFFER_SIZE +# define CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE 512 +#endif + +#ifndef CONFIG_EXAMPLES_NSH_CMD_SIZE +# define CONFIG_EXAMPLES_NSH_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_EXAMPLES_NSH_STACKSIZE +# define CONFIG_EXAMPLES_NSH_STACKSIZE 4096 +#endif + +/* Enabled dumping of all input/output buffers */ + +#undef CONFIG_EXAMPLES_NSH_TELNETD_DUMPBUFFER + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct telnetd_s +{ + int tn_sockfd; + char tn_iobuffer[CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE]; + char tn_cmd[CONFIG_EXAMPLES_NSH_CMD_SIZE]; + uint8 tn_bufndx; + uint8 tn_state; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_dumpbuffer + * + * Description: + * Dump a buffer of data (debug only) + * + ****************************************************************************/ + +#ifdef CONFIG_EXAMPLES_NSH_TELNETD_DUMPBUFFER +static void nsh_dumpbuffer(const char *msg, const char *buffer, ssize_t nbytes) +{ +#ifdef CONFIG_DEBUG + char line[128]; + int ch; + int i; + int j; + + dbg("%s:\n", msg); + for (i = 0; i < nbytes; i += 16) + { + sprintf(line, "%04x: ", i); + + for ( j = 0; j < 16; j++) + { + if (i + j < nbytes) + { + sprintf(&line[strlen(line)], "%02x ", buffer[i+j] ); + } + else + { + strcpy(&line[strlen(line)], " "); + } + } + + for ( j = 0; j < 16; j++) + { + if (i + j < nbytes) + { + ch = buffer[i+j]; + sprintf(&line[strlen(line)], "%c", ch >= 0x20 && ch <= 0x7e ? ch : '.'); + } + } + dbg("%s\n", line); + } +#endif +} +#else +# define nsh_dumpbuffer(msg,buffer,nbytes) +#endif + +/**************************************************************************** + * Name: nsh_putchar + * + * Description: + * Add another parsed character to the TELNET command string + * + ****************************************************************************/ + +static void nsh_putchar(struct telnetd_s *pstate, uint8 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_EXAMPLES_NSH_CMD_SIZE - 1)) + { + if (pstate->tn_bufndx > 0) + { + pstate->tn_cmd[pstate->tn_bufndx] = '\0'; + } + + nsh_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd)); + nsh_parse((void*)pstate, pstate->tn_cmd); + pstate->tn_bufndx = 0; + } + else + { + pstate->tn_bufndx++; + vdbg("Add '%c', bufndx=%d\n", ch, pstate->tn_bufndx); + } +} + +/**************************************************************************** + * Name: nsh_sendopt + * + * Description: + * + ****************************************************************************/ + +static void nsh_sendopt(struct telnetd_s *pstate, uint8 option, uint8 value) +{ + uint8 optbuf[4]; + optbuf[0] = TELNET_IAC; + optbuf[1] = option; + optbuf[2] = value; + optbuf[3] = 0; + + nsh_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: nsh_receive + * + * Description: + * Process a received TELENET buffer + * + ****************************************************************************/ + +static int nsh_receive(struct telnetd_s *pstate, size_t len) +{ + char *ptr = pstate->tn_iobuffer; + uint8 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) + { + nsh_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 */ + + nsh_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_WONT: + /* Reply with a DONT */ + + nsh_sendopt(pstate, TELNET_DONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_DO: + /* Reply with a WONT */ + + nsh_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_DONT: + /* Reply with a WONT */ + + nsh_sendopt(pstate, TELNET_WONT, ch); + pstate->tn_state = STATE_NORMAL; + break; + + case STATE_NORMAL: + if (ch == TELNET_IAC) + { + pstate->tn_state = STATE_IAC; + } + else + { + nsh_putchar(pstate, ch); + } + break; + } + } + return OK; +} + +/**************************************************************************** + * Name: nsh_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. + * + ****************************************************************************/ + +static void nsh_prompt(struct telnetd_s *pstate, const char *str) +{ + int len = strlen(str); + + strncpy(pstate->tn_iobuffer, str, len); + nsh_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: nsh_connection + * + * 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 *nsh_connection(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; + + /* Loop processing each TELNET command */ + + do + { + /* Display the prompt string */ + + nsh_prompt(pstate, g_nshprompt); + + /* Read a buffer of data from the TELNET client */ + + ret = recv(pstate->tn_sockfd, pstate->tn_iobuffer, CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE, 0); + if (ret > 0) + { + + /* Process the received TELNET data */ + + nsh_dumpbuffer("Received buffer", pstate->tn_iobuffer, ret); + ret = nsh_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); + pthread_exit(NULL); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_telnetmain + * + * Description: + * This is the main processing thread for telnetd. It never returns + * unless an error occurs + * + ****************************************************************************/ + +int nsh_telnetmain(void) +{ + struct in_addr addr; +#if defined(CONFIG_EXAMPLES_NSH_DHCPC) || defined(CONFIG_EXAMPLES_NSH_NOMAC) + uint8 mac[IFHWADDRLEN]; +#endif + +/* Many embedded network interfaces must have a software assigned MAC */ + +#ifdef CONFIG_EXAMPLES_NSH_NOMAC + mac[0] = 0x00; + mac[1] = 0xe0; + mac[2] = 0xb0; + mac[3] = 0x0b; + mac[4] = 0xba; + mac[5] = 0xbe; + uip_setmacaddr("eth0", mac); +#endif + + /* Set up our host address */ + +#if !defined(CONFIG_EXAMPLES_NSH_DHCPC) + addr.s_addr = HTONL(CONFIG_EXAMPLES_NSH_IPADDR); +#else + addr.s_addr = 0; +#endif + uip_sethostaddr("eth0", &addr); + + /* Set up the default router address */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_NSH_DRIPADDR); + uip_setdraddr("eth0", &addr); + + /* Setup the subnet mask */ + + addr.s_addr = HTONL(CONFIG_EXAMPLES_NSH_NETMASK); + uip_setnetmask("eth0", &addr); + +#if defined(CONFIG_EXAMPLES_NSH_DHCPC) + /* Set up the resolver */ + + resolv_init(); +#endif + +#if defined(CONFIG_EXAMPLES_NSH_DHCPC) + /* Get the MAC address of the NIC */ + + uip_getmacaddr("eth0", mac); + + /* Set up the DHCPC modules */ + + handle = dhcpc_open(&mac, IFHWADDRLEN); + + /* Get an IP address */ + + if (handle) + { + struct dhcpc_state ds; + (void)dhcpc_request(handle, &ds); + uip_sethostaddr("eth1", &ds.ipaddr); + if (ds.netmask.s_addr != 0) + { + uip_setnetmask("eth0", &ds.netmask); + } + if (ds.default_router.s_addr != 0) + { + uip_setdraddr("eth0", &ds.default_router); + } + if (ds.dnsaddr.s_addr != 0) + { + resolv_conf(&ds.dnsaddr); + } + dhcpc_close(handle); + } +#endif + + /* Execute nsh_connection on each connection to port 23 */ + + uip_server(HTONS(23), nsh_connection, CONFIG_EXAMPLES_NSH_STACKSIZE); + return OK; +} + +/**************************************************************************** + * Name: nsh_telnetout + * + * Description: + * Print a string to the remote 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. + * + ****************************************************************************/ + +int nsh_telnetout(FAR 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_EXAMPLES_NSH_IOBUFFER_SIZE, fmt, ap); + va_end(ap); + + len = strlen(pstate->tn_iobuffer); + if (len < (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 1) && pstate->tn_iobuffer[len-1] == '\n') + { + pstate->tn_iobuffer[len-1] = ISO_cr; + pstate->tn_iobuffer[len] = ISO_nl; + pstate->tn_iobuffer[len+1] = '\0'; + len++; + } + + nsh_dumpbuffer("Shell output", pstate->tn_iobuffer, len); + if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len, 0) < 0) + { + dbg("[%d] Failed to send response\n", pstate->tn_sockfd); + return ERROR; + } + + return len; +} + +/**************************************************************************** + * Name: cmd_exit + * + * Description: + * Quit the shell instance + * + ****************************************************************************/ + +void cmd_exit(void *handle, int argc, char **argv) +{ + struct telnetd_s *pstate = (struct telnetd_s *)handle; + pstate->tn_state = STATE_CLOSE; +} + diff --git a/fs/fs_closedir.c b/fs/fs_closedir.c index 5f20743c8f..50f2878ddc 100644 --- a/fs/fs_closedir.c +++ b/fs/fs_closedir.c @@ -134,9 +134,11 @@ int closedir(FAR DIR *dirp) free(idir); return OK; +#ifndef CONFIG_DISABLE_MOUNTPOINT errout_with_inode: inode_release(inode); free(idir); +#endif errout: *get_errno_ptr() = ret; diff --git a/fs/fs_opendir.c b/fs/fs_opendir.c index 82ce905f2e..3d174a640b 100644 --- a/fs/fs_opendir.c +++ b/fs/fs_opendir.c @@ -219,10 +219,14 @@ FAR DIR *opendir(const char *path) /* Nasty goto's make error handling simpler */ +#ifndef CONFIG_DISABLE_MOUNTPOINT errout_with_inode: inode_release(inode); +#endif + errout_with_direntry: free(dir); + errout_with_semaphore: inode_semgive(); *get_errno_ptr() = ret; diff --git a/net/accept.c b/net/accept.c index 0541fa0617..07db1ef303 100644 --- a/net/accept.c +++ b/net/accept.c @@ -62,14 +62,14 @@ struct accept_s { - sem_t acpt_sem; /* Wait for interrupt event */ + sem_t acpt_sem; /* Wait for interrupt event */ #ifdef CONFIG_NET_IPv6 - FAR const struct sockaddr_in6 *acpt_addr; /* Return connection adress */ + FAR struct sockaddr_in6 *acpt_addr; /* Return connection adress */ #else - FAR const struct sockaddr_in *acpt_addr; /* Return connection adress */ + FAR struct sockaddr_in *acpt_addr; /* Return connection adress */ #endif - FAR struct uip_conn *acpt_newconn; /* The accepted connection */ - int acpt_result; /* The result of the wait */ + FAR struct uip_conn *acpt_newconn; /* The accepted connection */ + int acpt_result; /* The result of the wait */ }; /**************************************************************************** @@ -242,9 +242,9 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) FAR struct uip_conn *conn; struct accept_s state; #ifdef CONFIG_NET_IPv6 - FAR const struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; + FAR struct sockaddr_in6 *inaddr = (const struct sockaddr_in6 *)addr; #else - FAR const struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; + FAR struct sockaddr_in *inaddr = (const struct sockaddr_in *)addr; #endif irqstate_t save; int newfd; diff --git a/net/recvfrom.c b/net/recvfrom.c index 43d3485afc..9013b6faed 100644 --- a/net/recvfrom.c +++ b/net/recvfrom.c @@ -831,7 +831,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, struct uip_conn *conn; struct recvfrom_s state; irqstate_t save; - int ret; + int ret = OK; /* Verify that the SOCK_STREAM has been connected */ diff --git a/netutils/telnetd/telnetd.c b/netutils/telnetd/telnetd.c index 64d14842d9..84e692221f 100644 --- a/netutils/telnetd/telnetd.c +++ b/netutils/telnetd/telnetd.c @@ -469,7 +469,7 @@ void shell_output(void *handle, const char *fmt, ...) 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 prompt\n", pstate->tn_sockfd); + dbg("[%d] Failed to send response\n", pstate->tn_sockfd); } }