summaryrefslogtreecommitdiff
path: root/nuttx/examples/nsh
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-08-16 18:39:46 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-08-16 18:39:46 +0000
commit07656e5f84288c96e871a522bb48e050ceec8551 (patch)
tree9ee3ba0a23a3c660076204af8b2a7fbf399c5ff2 /nuttx/examples/nsh
parent4764ba54f9306b0e39ccf5e3a0dd2f40604ea848 (diff)
downloadpx4-nuttx-07656e5f84288c96e871a522bb48e050ceec8551.tar.gz
px4-nuttx-07656e5f84288c96e871a522bb48e050ceec8551.tar.bz2
px4-nuttx-07656e5f84288c96e871a522bb48e050ceec8551.zip
NSH redirected output
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@823 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/examples/nsh')
-rw-r--r--nuttx/examples/nsh/Makefile6
-rw-r--r--nuttx/examples/nsh/nsh.h95
-rw-r--r--nuttx/examples/nsh/nsh_envcmds.c16
-rw-r--r--nuttx/examples/nsh/nsh_fscmds.c112
-rw-r--r--nuttx/examples/nsh/nsh_main.c505
-rw-r--r--nuttx/examples/nsh/nsh_netcmds.c101
-rw-r--r--nuttx/examples/nsh/nsh_proccmds.c31
-rw-r--r--nuttx/examples/nsh/nsh_serial.c213
-rw-r--r--nuttx/examples/nsh/nsh_telnetd.c195
9 files changed, 827 insertions, 447 deletions
diff --git a/nuttx/examples/nsh/Makefile b/nuttx/examples/nsh/Makefile
index 2f1c2c804..931ba2b16 100644
--- a/nuttx/examples/nsh/Makefile
+++ b/nuttx/examples/nsh/Makefile
@@ -45,10 +45,12 @@ CSRCS += nsh_netcmds.c
endif
endif
+ifeq ($(CONFIG_EXAMPLES_NSH_CONSOLE),y)
+CSRCS += nsh_serial.c
+endif
+
ifeq ($(CONFIG_EXAMPLES_NSH_TELNET),y)
CSRCS += nsh_telnetd.c
-else
-CSRCS += nsh_serial.c
endif
AOBJS = $(ASRCS:.S=$(OBJEXT))
diff --git a/nuttx/examples/nsh/nsh.h b/nuttx/examples/nsh/nsh.h
index ff6df6b24..77877908b 100644
--- a/nuttx/examples/nsh/nsh.h
+++ b/nuttx/examples/nsh/nsh.h
@@ -41,8 +41,7 @@
****************************************************************************/
#include <nuttx/config.h>
-#ifdef CONFIG_EXAMPLES_NSH_TELNET
-#else
+#ifdef CONFIG_EXAMPLES_NSH_CONSOLE
# include <stdio.h>
#endif
@@ -50,6 +49,10 @@
* Definitions
****************************************************************************/
+#if !defined(CONFIG_EXAMPLES_NSH_CONSOLE) && !defined(CONFIG_EXAMPLES_NSH_TELNET)
+# error "No NSH front end defined"
+#endif
+
/* This is the maximum number of arguments that will be accepted for a command */
#define NSH_MAX_ARGUMENTS 6
@@ -89,11 +92,35 @@
#undef CONFIG_EXAMPLES_NSH_TELNETD_DUMPBUFFER
#undef CONFIG_EXAMPLES_NSH_FULLPATH
+#define nsh_clone(v) (v)->clone(v)
+#define nsh_addref(v) (v)->addref(v)
+#define nsh_release(v) (v)->release(v)
+#define nsh_linebuffer(v) (v)->linebuffer(v)
+#define nsh_redirect(v,f) (v)->redirect(v,f)
+#define nsh_undirect(v,d) (v)->undirect(v,d)
+
+#ifdef CONFIG_CPP_HAVE_VARARGS
+# define nsh_output(v, fmt...) (v)->output(v, ##fmt)
+#else
+# define nsh_output vtbl->output
+#endif
+
/****************************************************************************
* Public Types
****************************************************************************/
-typedef void (*cmd_t)(FAR void *handle, int argc, char **argv);
+struct nsh_vtbl_s
+{
+ FAR struct nsh_vtbl_s *(*clone)(FAR struct nsh_vtbl_s *vtbl);
+ void (*addref)(FAR struct nsh_vtbl_s *vtbl);
+ void (*release)(FAR struct nsh_vtbl_s *vtbl);
+ int (*output)(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
+ FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl);
+ FAR void *(*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd);
+ void (*undirect)(FAR struct nsh_vtbl_s *vtbl, FAR void *direct);
+};
+
+typedef void (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
/****************************************************************************
* Public Data
@@ -115,67 +142,57 @@ extern const char g_fmtcmdoutofmemory[];
/* Message handler */
-extern int nsh_parse(FAR void *handle, char *cmdline);
+extern int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline);
/* I/O interfaces */
-extern int nsh_main(void);
-extern int nsh_output(FAR void *handle, const char *fmt, ...);
-extern FAR char *nsh_linebuffer(FAR void *handle);
+#ifdef CONFIG_EXAMPLES_NSH_CONSOLE
+extern int nsh_consolemain(int argc, char *argv[]);
+#endif
-#ifndef CONFIG_EXAMPLES_NSH_TELNET /* Not yet supported on telnetd interface */
-extern FAR void *nsh_clone(FAR void *handle);
-extern void nsh_addref(FAR void *handle);
-extern void nsh_release(FAR void *handle);
-extern void *nsh_redirect(int fd);
-extern void nsh_restore(void *direct);
-#else
-# define nsh_clone(handle) (handle)
-# define nsh_addref(handle)
-# define nsh_release(handle);
-# define nsh_redirect(fd) (NULL);
-# define nsh_restore(direct)
+#ifdef CONFIG_EXAMPLES_NSH_TELNET
+extern int nsh_telnetmain(int argc, char *argv[]);
#endif
/* Shell command handlers */
-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);
-extern void cmd_ps(FAR void *handle, int argc, char **argv);
+extern void cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern void cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern void cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+extern void cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#if CONFIG_NFILE_DESCRIPTORS > 0
- extern void cmd_cat(FAR void *handle, int argc, char **argv);
- extern void cmd_cp(FAR void *handle, int argc, char **argv);
- extern void cmd_ls(FAR void *handle, int argc, char **argv);
+ extern void cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# if CONFIG_NFILE_STREAMS > 0
- extern void cmd_sh(FAR void *handle, int argc, char **argv);
+ extern void cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif /* CONFIG_NFILE_STREAMS */
# ifndef CONFIG_DISABLE_MOUNTPOINT
- extern void cmd_mkdir(FAR void *handle, int argc, char **argv);
- extern void cmd_mkfifo(FAR void *handle, 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_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# ifdef CONFIG_FS_FAT
- extern void cmd_mkfatfs(FAR void *handle, int argc, char **argv);
- extern void cmd_mount(FAR void *handle, int argc, char **argv);
- extern void cmd_umount(FAR void *handle, int argc, char **argv);
+ extern void cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
# endif /* CONFIG_FS_FAT */
# endif /* !CONFIG_DISABLE_MOUNTPOINT */
#endif /* CONFIG_NFILE_DESCRIPTORS */
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
- extern void cmd_ifconfig(FAR void *handle, int argc, char **argv);
+ extern void cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif
#ifndef CONFIG_DISABLE_ENVIRON
- extern void cmd_set(FAR void *handle, int argc, char **argv);
- extern void cmd_unset(FAR void *handle, int argc, char **argv);
+ extern void cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif /* CONFIG_DISABLE_ENVIRON */
#ifndef CONFIG_DISABLE_SIGNALS
- extern void cmd_sleep(FAR void *handle, int argc, char **argv);
- extern void cmd_usleep(FAR void *handle, int argc, char **argv);
+ extern void cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern void cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif /* CONFIG_DISABLE_SIGNALS */
#endif /* __NSH_H */
diff --git a/nuttx/examples/nsh/nsh_envcmds.c b/nuttx/examples/nsh/nsh_envcmds.c
index 0a96206df..ce05fab82 100644
--- a/nuttx/examples/nsh/nsh_envcmds.c
+++ b/nuttx/examples/nsh/nsh_envcmds.c
@@ -79,7 +79,7 @@
* Name: cmd_echo
****************************************************************************/
-void cmd_echo(FAR void *handle, int argc, char **argv)
+void cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
int i;
@@ -97,16 +97,16 @@ void cmd_echo(FAR void *handle, int argc, char **argv)
char *value = getenv(argv[i]+1);
if (value)
{
- nsh_output(handle, "%s ", value);
+ nsh_output(vtbl, "%s ", value);
}
}
else
#endif
{
- nsh_output(handle, "%s ", argv[i]);
+ nsh_output(vtbl, "%s ", argv[i]);
}
}
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
}
/****************************************************************************
@@ -114,11 +114,11 @@ void cmd_echo(FAR void *handle, int argc, char **argv)
****************************************************************************/
#ifndef CONFIG_DISABLE_ENVIRON
-void cmd_set(FAR void *handle, int argc, char **argv)
+void cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
if (setenv(argv[1], argv[2], TRUE) < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO);
}
}
#endif
@@ -128,11 +128,11 @@ void cmd_set(FAR void *handle, int argc, char **argv)
****************************************************************************/
#ifndef CONFIG_DISABLE_ENVIRON
-void cmd_unset(FAR void *handle, int argc, char **argv)
+void cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
if (unsetenv(argv[1]) < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO);
}
}
#endif
diff --git a/nuttx/examples/nsh/nsh_fscmds.c b/nuttx/examples/nsh/nsh_fscmds.c
index 7650c8144..06ced9a04 100644
--- a/nuttx/examples/nsh/nsh_fscmds.c
+++ b/nuttx/examples/nsh/nsh_fscmds.c
@@ -93,7 +93,7 @@
* Private Types
****************************************************************************/
-typedef int (*direntry_handler_t)(FAR void *, const char *, struct dirent *, void *);
+typedef int (*direntry_handler_t)(FAR struct nsh_vtbl_s *, const char *, struct dirent *, void *);
/****************************************************************************
* Private Function Prototypes
@@ -105,7 +105,7 @@ typedef int (*direntry_handler_t)(FAR void *, const char *, struct dirent *, voi
/* Common buffer for file I/O. Note the use of this common buffer precludes
* multiple copies of NSH running concurrently. It should be allocated per
- * NSH instance and retained in the "handle" as is done for the telnet
+ * NSH instance and retained in the "vtbl" as is done for the telnet
* connection.
*/
@@ -161,7 +161,7 @@ static char *getdirpath(const char *path, const char *file)
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-static int foreach_direntry(FAR void *handle, const char *cmd, const char *dirpath,
+static int foreach_direntry(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *dirpath,
direntry_handler_t handler, void *pvarg)
{
DIR *dirp;
@@ -181,7 +181,7 @@ static int foreach_direntry(FAR void *handle, const char *cmd, const char *dirpa
{
/* Failed to open the directory */
- nsh_output(handle, g_fmtnosuch, cmd, "directory", dirpath);
+ nsh_output(vtbl, g_fmtnosuch, cmd, "directory", dirpath);
return ERROR;
}
@@ -199,7 +199,7 @@ static int foreach_direntry(FAR void *handle, const char *cmd, const char *dirpa
/* Call the handler with this directory entry */
- if (handler(handle, dirpath, entryp, pvarg) < 0)
+ if (handler(vtbl, dirpath, entryp, pvarg) < 0)
{
/* The handler reported a problem */
@@ -218,7 +218,7 @@ static int foreach_direntry(FAR void *handle, const char *cmd, const char *dirpa
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-static int ls_handler(FAR void *handle, const char *dirpath, struct dirent *entryp, void *pvarg)
+static int ls_handler(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, struct dirent *entryp, void *pvarg)
{
unsigned int lsflags = (unsigned int)pvarg;
int ret;
@@ -236,7 +236,7 @@ static int ls_handler(FAR void *handle, const char *dirpath, struct dirent *entr
free(fullpath);
if (ret != 0)
{
- nsh_output(handle, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO);
return OK;
}
@@ -301,30 +301,30 @@ static int ls_handler(FAR void *handle, const char *dirpath, struct dirent *entr
details[9]='x';
}
- nsh_output(handle, " %s", details);
+ nsh_output(vtbl, " %s", details);
}
if ((lsflags & LSFLAGS_SIZE) != 0)
{
- nsh_output(handle, "%8d", buf.st_size);
+ nsh_output(vtbl, "%8d", buf.st_size);
}
}
/* then provide the filename that is common to normal and verbose output */
#ifdef CONFIG_EXAMPLES_NSH_FULLPATH
- nsh_output(handle, " %s/%s", arg, entryp->d_name);
+ nsh_output(vtbl, " %s/%s", arg, entryp->d_name);
#else
- nsh_output(handle, " %s", entryp->d_name);
+ nsh_output(vtbl, " %s", entryp->d_name);
#endif
if (DIRENT_ISDIRECTORY(entryp->d_type))
{
- nsh_output(handle, "/\n");
+ nsh_output(vtbl, "/\n");
}
else
{
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
}
return OK;
}
@@ -335,7 +335,7 @@ static int ls_handler(FAR void *handle, const char *dirpath, struct dirent *entr
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-static int ls_recursive(FAR void *handle, const char *dirpath, struct dirent *entryp, void *pvarg)
+static int ls_recursive(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, struct dirent *entryp, void *pvarg)
{
/* Is this entry a directory? */
@@ -348,12 +348,12 @@ static int ls_recursive(FAR void *handle, const char *dirpath, struct dirent *en
/* List the directory contents */
- nsh_output(handle, "%s:\n", newpath);
- foreach_direntry(handle, "ls", newpath, ls_handler, pvarg);
+ nsh_output(vtbl, "%s:\n", newpath);
+ foreach_direntry(vtbl, "ls", newpath, ls_handler, pvarg);
/* Then recurse to list each directory within the directory */
- foreach_direntry(handle, "ls", newpath, ls_recursive, pvarg);
+ foreach_direntry(vtbl, "ls", newpath, ls_recursive, pvarg);
free(newpath);
}
return OK;
@@ -369,7 +369,7 @@ static int ls_recursive(FAR void *handle, const char *dirpath, struct dirent *en
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_cat(FAR void *handle, int argc, char **argv)
+void cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
char buffer[IOBUFFERSIZE];
@@ -378,7 +378,7 @@ void cmd_cat(FAR void *handle, int argc, char **argv)
int fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
return;
}
@@ -396,7 +396,7 @@ void cmd_cat(FAR void *handle, int argc, char **argv)
if (errno != EINTR)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
break;
}
}
@@ -416,7 +416,7 @@ void cmd_cat(FAR void *handle, int argc, char **argv)
if (errno != EINTR)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO);
break;
}
}
@@ -444,7 +444,7 @@ void cmd_cat(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_cp(FAR void *handle, int argc, char **argv)
+void cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
struct stat buf;
char *fullpath = NULL;
@@ -459,7 +459,7 @@ void cmd_cp(FAR void *handle, int argc, char **argv)
rdfd = open(argv[1], O_RDONLY);
if (rdfd < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
return;
}
@@ -481,7 +481,7 @@ void cmd_cp(FAR void *handle, int argc, char **argv)
fullpath = getdirpath(argv[2], basename(argv[1]) );
if (!fullpath)
{
- nsh_output(handle, g_fmtcmdoutofmemory, argv[0]);
+ nsh_output(vtbl, g_fmtcmdoutofmemory, argv[0]);
goto out_with_rdfd;
}
@@ -501,7 +501,7 @@ void cmd_cp(FAR void *handle, int argc, char **argv)
wrfd = open(wrpath, oflags, 0666);
if (wrfd < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
goto out_with_fullpath;
}
@@ -525,7 +525,7 @@ void cmd_cp(FAR void *handle, int argc, char **argv)
{
/* Read error */
- nsh_output(handle, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
goto out_with_wrfd;
}
}
@@ -542,7 +542,7 @@ void cmd_cp(FAR void *handle, int argc, char **argv)
{
/* Read error */
- nsh_output(handle, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO);
goto out_with_wrfd;
}
}
@@ -568,7 +568,7 @@ out_with_rdfd:
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_ls(FAR void *handle, int argc, char **argv)
+void cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
unsigned int lsflags = 0;
int ret;
@@ -594,7 +594,7 @@ void cmd_ls(FAR void *handle, int argc, char **argv)
case '?':
default:
- nsh_output(handle, g_fmtarginvalid, argv[0]);
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return;
}
}
@@ -603,24 +603,24 @@ void cmd_ls(FAR void *handle, int argc, char **argv)
if (optind + 1 < argc)
{
- nsh_output(handle, g_fmttoomanyargs, argv[0]);
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
return;
}
else if (optind + 1 > argc)
{
- nsh_output(handle, g_fmtargrequired, argv[0]);
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
return;
}
/* List the directory contents */
- nsh_output(handle, "%s:\n", argv[optind]);
- ret = foreach_direntry(handle, "ls", argv[optind], ls_handler, (void*)lsflags);
+ nsh_output(vtbl, "%s:\n", argv[optind]);
+ ret = foreach_direntry(vtbl, "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(handle, "ls", argv[optind], ls_recursive, (void*)lsflags);
+ ret = foreach_direntry(vtbl, "ls", argv[optind], ls_recursive, (void*)lsflags);
}
}
#endif
@@ -630,12 +630,12 @@ void cmd_ls(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_mkdir(FAR void *handle, int argc, char **argv)
+void cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
int result = mkdir(argv[1], 0777);
if ( result < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "mkdir", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkdir", NSH_ERRNO);
}
}
#endif
@@ -645,13 +645,13 @@ void cmd_mkdir(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT)
-void cmd_mkfatfs(FAR void *handle, int argc, char **argv)
+void cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
struct fat_format_s fmt = FAT_FORMAT_INITIALIZER;
int result = mkfatfs(argv[1], &fmt);
if ( result < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "mkfatfs", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfatfs", NSH_ERRNO);
}
}
#endif
@@ -661,12 +661,12 @@ void cmd_mkfatfs(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_mkfifo(FAR void *handle, int argc, char **argv)
+void cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
int result = mkfifo(argv[1], 0777);
if ( result < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "mkfifo", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfifo", NSH_ERRNO);
}
}
#endif
@@ -677,7 +677,7 @@ void cmd_mkfifo(FAR void *handle, int argc, char **argv)
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
#ifdef CONFIG_FS_FAT /* Need at least one filesytem in configuration */
-void cmd_mount(FAR void *handle, int argc, char **argv)
+void cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
char *filesystem = 0;
int result;
@@ -694,12 +694,12 @@ void cmd_mount(FAR void *handle, int argc, char **argv)
break;
case ':':
- nsh_output(handle, g_fmtargrequired, argv[0]);
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
return;
case '?':
default:
- nsh_output(handle, g_fmtarginvalid, argv[0]);
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return;
}
}
@@ -708,12 +708,12 @@ void cmd_mount(FAR void *handle, int argc, char **argv)
if (optind + 2 < argc)
{
- nsh_output(handle, g_fmttoomanyargs, argv[0]);
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
return;
}
else if (optind + 2 > argc)
{
- nsh_output(handle, g_fmtargrequired, argv[0]);
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
return;
}
@@ -721,7 +721,7 @@ void cmd_mount(FAR void *handle, int argc, char **argv)
result = mount(argv[optind], argv[optind+1], filesystem, 0, NULL);
if ( result < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
}
}
#endif
@@ -732,11 +732,11 @@ void cmd_mount(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_rm(FAR void *handle, int argc, char **argv)
+void cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
if (unlink(argv[1]) < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "unlink", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unlink", NSH_ERRNO);
}
}
#endif
@@ -746,11 +746,11 @@ void cmd_rm(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
-void cmd_rmdir(FAR void *handle, int argc, char **argv)
+void cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
if (rmdir(argv[1]) < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "rmdir", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmdir", NSH_ERRNO);
}
}
#endif
@@ -760,7 +760,7 @@ void cmd_rmdir(FAR void *handle, int argc, char **argv)
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
-void cmd_sh(FAR void *handle, int argc, char **argv)
+void cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
FILE *stream;
char *buffer;
@@ -768,13 +768,13 @@ void cmd_sh(FAR void *handle, int argc, char **argv)
/* Get a reference to the common input buffer */
- buffer = nsh_linebuffer(handle);
+ buffer = nsh_linebuffer(vtbl);
if (buffer)
{
stream = fopen(argv[1], "r");
if (!stream)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "fopen", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "fopen", NSH_ERRNO);
return;
}
@@ -791,7 +791,7 @@ void cmd_sh(FAR void *handle, int argc, char **argv)
* considerable amount of stack may be used.
*/
- (void)nsh_parse(handle, buffer);
+ (void)nsh_parse(vtbl, buffer);
}
}
while(pret);
@@ -806,13 +806,13 @@ void cmd_sh(FAR void *handle, int argc, char **argv)
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
#ifdef CONFIG_FS_FAT /* Need at least one filesytem in configuration */
-void cmd_umount(FAR void *handle, int argc, char **argv)
+void cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
/* Perform the umount */
int result = umount(argv[1]);
if ( result < 0)
{
- nsh_output(handle, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO);
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO);
}
}
#endif
diff --git a/nuttx/examples/nsh/nsh_main.c b/nuttx/examples/nsh/nsh_main.c
index cf20141cb..c2754ae3f 100644
--- a/nuttx/examples/nsh/nsh_main.c
+++ b/nuttx/examples/nsh/nsh_main.c
@@ -39,11 +39,14 @@
#include <nuttx/config.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
#include <sched.h>
+#include <fcntl.h>
#include <errno.h>
#include "nsh.h"
@@ -69,14 +72,16 @@ struct cmdmap_s
* Private Function Prototypes
****************************************************************************/
-static void cmd_help(FAR void *handle, int argc, char **argv);
-static void cmd_unrecognized(FAR void *handle, int argc, char **argv);
+static void cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+static void cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
/****************************************************************************
* Private Data
****************************************************************************/
-static const char delim[] = " \t\n";
+static const char g_delim[] = " \t\n";
+static const char g_redirect1[] = ">";
+static const char g_redirect2[] = ">>";
static const struct cmdmap_s g_cmdmap[] =
{
@@ -162,21 +167,22 @@ const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n";
* Name: cmd_help
****************************************************************************/
-static void cmd_help(FAR void *handle, int argc, char **argv)
+static void cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
const struct cmdmap_s *ptr;
- nsh_output(handle, "NSH commands:\n");
- nsh_output(handle, " nice [-d] <cmd> &\n");
+ nsh_output(vtbl, "NSH command form:\n");
+ nsh_output(vtbl, " [nice [-d <niceness>>]] <cmd> [[> <file>|>> <file>] &]\n");
+ nsh_output(vtbl, "Where <cmd> is one of:\n");
for (ptr = g_cmdmap; ptr->cmd; ptr++)
{
if (ptr->usage)
{
- nsh_output(handle, " %s %s\n", ptr->cmd, ptr->usage);
+ nsh_output(vtbl, " %s %s\n", ptr->cmd, ptr->usage);
}
else
{
- nsh_output(handle, " %s\n", ptr->cmd);
+ nsh_output(vtbl, " %s\n", ptr->cmd);
}
}
}
@@ -185,9 +191,9 @@ static void cmd_help(FAR void *handle, int argc, char **argv)
* Name: cmd_unrecognized
****************************************************************************/
-static void cmd_unrecognized(FAR void *handle, int argc, char **argv)
+static void cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- nsh_output(handle, g_fmtcmdnotfound, argv[0]);
+ nsh_output(vtbl, g_fmtcmdnotfound, argv[0]);
}
/****************************************************************************
@@ -198,23 +204,25 @@ static int nsh_execute(int argc, char *argv[])
{
const struct cmdmap_s *cmdmap;
const char *cmd;
- void *handle;
+ struct nsh_vtbl_s *vtbl;
cmd_t handler = cmd_unrecognized;
/* Parse all of the arguments following the command name. The form
* of argv is:
*
- * argv[0]: Task name "nsh_execute"
- * argv[1]: This is string version of the handle needed to execute
- * the command (under telnetd). It is a string because
- * binary values cannot be provided via char *argv[]
- * argv[2]: The command name. This is argv[0] when the arguments
- * are, finally, received by the command handler
- * argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
- * argv[argc]: NULL terminating pointer
+ * argv[0]: Task name "nsh_execute"
+ * argv[1]: This is string version of the vtbl needed to execute
+ * the command (under telnetd). It is a string because
+ * binary values cannot be provided via char *argv[]
+ * argv[2]: The command name. This is argv[0] when the arguments
+ * are, finally, received by the command vtblr
+ * argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
+ * argv[argc]: NULL terminating pointer
+ *
+ * Maximum size is NSH_MAX_ARGUMENTS+4
*/
- handle = (void*)strtol(argv[1], NULL, 16);
+ vtbl = (struct nsh_vtbl_s*)strtol(argv[1], NULL, 16);
cmd = argv[2];
argc -= 2;
@@ -233,14 +241,14 @@ static int nsh_execute(int argc, char *argv[])
{
/* Fewer than the minimum number were provided */
- nsh_output(handle, g_fmtargrequired, cmd);
+ nsh_output(vtbl, g_fmtargrequired, cmd);
return ERROR;
}
else if (argc > cmdmap->maxargs)
{
/* More than the maximum number were provided */
- nsh_output(handle, g_fmttoomanyargs, cmd);
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
return ERROR;
}
else
@@ -255,23 +263,93 @@ static int nsh_execute(int argc, char *argv[])
}
}
- handler(handle, argc, &argv[2]);
- nsh_release(handle);
+ handler(vtbl, argc, &argv[2]);
+ nsh_release(vtbl);
return OK;
}
/****************************************************************************
- * Name: nsh_setprio
+ * Name: nsh_argument
****************************************************************************/
-static inline void nsh_setprio(void)
+char *nsh_argument(char **saveptr)
{
- int max_priority = sched_get_priority_max(SCHED_RR);
- int min_priority = sched_get_priority_min(SCHED_RR);
- struct sched_param param;
+ char *pbegin = *saveptr;
+ char *pend = NULL;
+ const char *term;
+
+ /* Find the beginning of the next token */
+
+ for (;
+ *pbegin && strchr(g_delim, *pbegin) != NULL;
+ pbegin++);
+
+ /* If we are at the end of the string with nothing
+ * but delimiters found, then return NULL.
+ */
+
+ if (!*pbegin)
+ {
+ return NULL;
+ }
+
+ /* Does the token begin with '>' */
- param.sched_priority = (max_priority + min_priority) >> 1;
- (void)sched_setscheduler(0, SCHED_RR, &param);
+ if (*pbegin == '>')
+ {
+ /* Yes.. does it begin with ">>"? */
+
+ if (*(pbegin + 1) == '>')
+ {
+ *saveptr = pbegin + 2;
+ return (char*)g_redirect2;
+ }
+ else
+ {
+ *saveptr = pbegin + 1;
+ return (char*)g_redirect1;
+ }
+ }
+
+ /* Does the token begin with '"'? */
+
+ else if (*pbegin == '"')
+ {
+ /* Yes.. then only another '"' can terminate the string */
+
+ pbegin++;
+ term = "\"";
+ }
+ else
+ {
+ /* No, then any of the usual terminators will terminate the argument */
+
+ term = g_delim;
+ }
+
+ /* Find the end of the string */
+
+ for (pend = pbegin + 1;
+ *pend && strchr(term, *pend) == NULL;
+ pend++);
+
+ /* pend either points to the end of the string or to
+ * the first delimiter after the string.
+ */
+
+ if (*pend)
+ {
+ /* Turn the delimiter into a null terminator */
+
+ *pend++ = '\0';
+ }
+
+ /* Save the pointer where we left off and return the
+ * beginning of the token.
+ */
+
+ *saveptr = pend;
+ return pbegin;
}
/****************************************************************************
@@ -293,22 +371,66 @@ void user_initialize(void)
int user_start(int argc, char *argv[])
{
- nsh_setprio();
- return nsh_main();
+ int mid_priority;
+ int ret;
+
+ /* Set the priority of this task to something in the middle so that 'nice'
+ * can both raise and lower the priority.
+ */
+
+ mid_priority = (sched_get_priority_max(SCHED_RR) + sched_get_priority_min(SCHED_RR)) >> 1;
+ {
+ struct sched_param param;
+
+ param.sched_priority = mid_priority;
+ (void)sched_setscheduler(0, SCHED_RR, &param);
+ }
+
+ /* If both the console and telnet are selected as front-ends, then run
+ * the telnet front end on another thread.
+ */
+
+#if defined(CONFIG_EXAMPLES_NSH_CONSOLE) && defined(CONFIG_EXAMPLES_NSH_TELNET)
+# ifndef CONFIG_CUSTOM_STACK
+ ret = task_create("nsh_telnetmain", mid_priority, CONFIG_EXAMPLES_NSH_STACKSIZE,
+ nsh_telnetmain, NULL);
+# else
+ ret = task_create("nsh_telnetmain", mid_priority, nsh_telnetmain, NULL);
+# endif
+ if (ret < 0)
+ {
+ fprintf(stderr, g_fmtcmdfailed, "user_start", "task_create", NSH_ERRNO);
+ }
+
+ /* If only the telnet front-end is selected, run it on this thread */
+
+#elif defined(CONFIG_EXAMPLES_NSH_TELNET)
+ return nsh_telnetmain(0, NULL);
+#endif
+
+/* If the serial console front end is selected, then run it on this thread */
+
+#ifdef CONFIG_EXAMPLES_NSH_CONSOLE
+ return nsh_consolemain(0, NULL);
+#endif
}
/****************************************************************************
* Name: nsh_parse
****************************************************************************/
-int nsh_parse(FAR void *handle, char *cmdline)
+int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
{
- FAR char *argv[NSH_MAX_ARGUMENTS+4];
- FAR char strhandle[2*sizeof(FAR char*)+3];
+ FAR char *argv[NSH_MAX_ARGUMENTS+7];
+ FAR char strvtbl[2*sizeof(FAR char*)+3];
FAR char *saveptr;
FAR char *cmd;
- boolean bg;
+ FAR char *redirfile;
+ boolean bg = FALSE;
+ boolean redirect = FALSE;
+ int fd = -1;
int nice = 0;
+ int oflags;
int argc;
int ret;
@@ -316,7 +438,8 @@ int nsh_parse(FAR void *handle, char *cmdline)
/* Parse out the command at the beginning of the line */
- cmd = strtok_r(cmdline, " \t\n", &saveptr);
+ saveptr = cmdline;
+ cmd = nsh_argument(&saveptr);
if (cmd)
{
/* Check if the command is preceded by "nice" */
@@ -331,20 +454,20 @@ int nsh_parse(FAR void *handle, char *cmdline)
/* Get the cmd (or -d option of nice command) */
- cmd = strtok_r(NULL, " \t\n", &saveptr);
+ cmd = nsh_argument(&saveptr);
if (cmd && strcmp(cmd, "-d") == 0)
{
- FAR char *val = strtok_r(NULL, " \t\n", &saveptr);
+ FAR char *val = nsh_argument(&saveptr);
if (val)
{
char *endptr;
nice = (int)strtol(val, &endptr, 0);
if (nice > 19 || nice < -20 || endptr == val || *endptr != '\0')
{
- nsh_output(handle, g_fmtarginvalid, "nice");
+ nsh_output(vtbl, g_fmtarginvalid, "nice");
return ERROR;
}
- cmd = strtok_r(NULL, " \t\n", &saveptr);
+ cmd = nsh_argument(&saveptr);
}
}
}
@@ -352,164 +475,242 @@ int nsh_parse(FAR void *handle, char *cmdline)
/* Check if any command was provided */
- if (cmd)
+ if (!cmd)
{
- /* Parse all of the arguments following the command name. The form
- * of argv is:
- *
- * argv[0]: Not really used. It is just a place hold for where the
- * task name would be if the same command were executed
- * in the "background"
- * argv[1]: This is string version of the handle needed to execute
- * the command (under telnetd). It is a string because
- * binary values cannot be provided via char *argv[]. NOTE
- * that this value is filled in later.
- * argv[2]: The command name. This is argv[0] when the arguments
- * are, finally, received by the command handler
- * argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
- * argv[argc]: NULL terminating pointer
- */
+ return OK; /* Newline only is not an error */
+ }
- argv[0] = "nsh_execute";
- argv[2] = cmd;
- for (argc = 3; argc < NSH_MAX_ARGUMENTS+4; argc++)
+ /* Parse all of the arguments following the command name. The form
+ * of argv is:
+ *
+ * argv[0]: Not really used. It is just a place hold for where the
+ * task name would be if the same command were executed
+ * in the "background"
+ * argv[1]: This is string version of the vtbl needed to execute
+ * the command (under telnetd). It is a string because
+ * binary values cannot be provided via char *argv[]. NOTE
+ * that this value is filled in later.
+ * argv[2]: The command name. This is argv[0] when the arguments
+ * are, finally, received by the command vtblr
+ * argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
+ * argv[argc-3]: Possibly '>' or '>>'
+ * argv[argc-2]: Possibly <file>
+ * argv[argc-1]: Possibly '&'
+ * argv[argc]: NULL terminating pointer
+ *
+ * Maximum size is NSH_MAX_ARGUMENTS+7
+ */
+
+ argv[0] = "nsh_execute";
+ argv[2] = cmd;
+ for (argc = 3; argc < NSH_MAX_ARGUMENTS+6; argc++)
+ {
+ argv[argc] = nsh_argument(&saveptr);
+ if (!argv[argc])
{
- argv[argc] = strtok_r(NULL, " \t\n", &saveptr);
- if (!argv[argc])
- {
- break;
- }
+ break;
}
+ }
+ argv[argc] = NULL;
- /* Check if the command should run in background */
+ /* Check if the command should run in background */
- bg = FALSE;
- if (strcmp(argv[argc-1], "&") == 0)
+ if (argc > 3 && strcmp(argv[argc-1], "&") == 0)
+ {
+ bg = TRUE;
+ argv[argc-1] = NULL;
+ argc--;
+ }
+
+ /* Check if the output was re-directed using > or >> */
+
+ if (argc > 5)
+ {
+ /* Check for redirection to a new file */
+
+ if (strcmp(argv[argc-2], g_redirect1) == 0)
{
- bg = TRUE;
- argv[argc-1] = NULL;
- argc--;
+ redirect = TRUE;
+ oflags = O_WRONLY|O_CREAT|O_TRUNC;
+ redirfile = argv[argc-1];
+ argc -= 2;
}
- if (argc > NSH_MAX_ARGUMENTS+3)
+ /* Check for redirection by appending to an existing file */
+
+ else if (strcmp(argv[argc-2], g_redirect2) == 0)
{
- nsh_output(handle, g_fmttoomanyargs, cmd);
+ redirect = TRUE;
+ oflags = O_WRONLY|O_CREAT|O_APPEND;
+ redirfile = argv[argc-1];
+ argc -= 2;
}
+ }
+
+ /* Redirected output? */
+
+ if (redirect)
+ {
+ /* Open the redirection file. This file will eventually
+ * be closed by a call to either nsh_release (if the command
+ * is executed in the background) or by nsh_undirect if the
+ * command is executed in the foreground.
+ */
- if (bg)
+ fd = open(redirfile, oflags, 0666);
+ if (fd < 0)
{
- struct sched_param param;
- int priority;
- void *bkghandle;
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO);
+ return ERROR;
+ }
+ }
- /* Get a cloned copy of the handle with reference count=1.
- * after the command has been processed, the nsh_release() call
- * at the end of nsh_execute() will destroy the clone.
- */
+ /* Check if the maximum number of arguments was exceeded */
- bkghandle = nsh_clone(handle);
+ if (argc > NSH_MAX_ARGUMENTS+3)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
+ }
- /* Place a string copy of the cloned handle in the argument list */
+ /* Handle the case where the command is executed in background */
- sprintf(strhandle, "%p\n", bkghandle);
- argv[1] = strhandle;
+ if (bg)
+ {
+ struct sched_param param;
+ int priority;
+ struct nsh_vtbl_s *bkgvtbl;
- /* Handle redirection of output via a file descriptor */
+ /* Get a cloned copy of the vtbl with reference count=1.
+ * after the command has been processed, the nsh_release() call
+ * at the end of nsh_execute() will destroy the clone.
+ */
- /* (void)nsh_redirect(bkghandle); */
+ bkgvtbl = nsh_clone(vtbl);
- /* Get the execution priority of this task */
+ /* Place a string copy of the cloned vtbl in the argument list */
- ret = sched_getparam(0, &param);
- if (ret != 0)
- {
- nsh_output(handle, g_fmtcmdfailed, cmd, "sched_getparm", NSH_ERRNO);
- return ERROR;
- }
+ sprintf(strvtbl, "%p\n", bkgvtbl);
+ argv[1] = strvtbl;
- /* Determine the priority to execute the command */
+ /* Handle redirection of output via a file descriptor */
- priority = param.sched_priority;
- if (nice != 0)
+ if (redirect)
+ {
+ (void)nsh_redirect(bkgvtbl, fd);
+ }
+
+ /* Get the execution priority of this task */
+
+ ret = sched_getparam(0, &param);
+ if (ret != 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "sched_getparm", NSH_ERRNO);
+ goto errout;
+ }
+
+ /* Determine the priority to execute the command */
+
+ priority = param.sched_priority;
+ if (nice != 0)
+ {
+ priority -= nice;
+ if (nice < 0)
{
- priority -= nice;
- if (nice < 0)
+ int max_priority = sched_get_priority_max(SCHED_RR);
+ if (priority > max_priority)
{
- int max_priority = sched_get_priority_max(SCHED_RR);
- if (priority > max_priority)
- {
- priority = max_priority;
- }
+ priority = max_priority;
}
- else
+ }
+ else
+ {
+ int min_priority = sched_get_priority_min(SCHED_RR);
+ if (priority < min_priority)
{
- int min_priority = sched_get_priority_min(SCHED_RR);
- if (priority < min_priority)
- {
- priority = min_priority;
- }
+ priority = min_priority;
}
}
+ }
- /* Execute the command as a separate task at the appropriate priority */
+ /* Execute the command as a separate task at the appropriate priority */
#ifndef CONFIG_CUSTOM_STACK
- ret = task_create("nsh_execute", priority, CONFIG_EXAMPLES_NSH_STACKSIZE,
- nsh_execute, &argv[1]);
+ ret = task_create("nsh_execute", priority, CONFIG_EXAMPLES_NSH_STACKSIZE,
+ nsh_execute, &argv[1]);
#else
- ret = task_create("nsh_execute", priority, nsh_execute, &argv[1]);
+ ret = task_create("nsh_execute", priority, nsh_execute, &argv[1]);
#endif
- if (ret < 0)
- {
- nsh_output(handle, g_fmtcmdfailed, cmd, "task_create", NSH_ERRNO);
- return ERROR;
- }
-#ifdef CONFIG_DEBUG
- nsh_output(handle, "%s [%d:%d:%d]\n", cmd, ret, priority, param.sched_priority);
-#else
- nsh_output(handle, "%s [%d]\n", cmd, ret);
-#endif
- }
- else
+ if (ret < 0)
{
- /* void *save; */
-
- /* Increment the reference count on the handle. This reference count will
- * be decremented at the end of nsh_execute() and exists only for compatibility
- * with the background command logic.
- */
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "task_create", NSH_ERRNO);
+ goto errout;
+ }
+ nsh_output(vtbl, "%s [%d:%d:%d]\n", cmd, ret, priority, param.sched_priority);
- nsh_addref(handle);
+ /* If the output was redirected, then file descriptor should
+ * be closed. The created task has its one, independent copy of
+ * the file descriptor
+ */
- /* Place a string copy of the original handle in the argument list */
+ if (redirect)
+ {
+ (void)close(fd);
+ }
+ }
+ else
+ {
+ void *save;
- sprintf(strhandle, "%p\n", handle);
- argv[1] = strhandle;
+ /* Increment the reference count on the vtbl. This reference count will
+ * be decremented at the end of nsh_execute() and exists only for compatibility
+ * with the background command logic.
+ */
- /* Handle redirection of output via a file descriptor */
- /* save = nsh_redirect(fd); */
+ nsh_addref(vtbl);
- /* Then execute the command in "foreground" -- i.e., while the user waits
- * for the next prompt.
- */
+ /* Place a string copy of the original vtbl in the argument list */
- ret = nsh_execute(argc, argv);
- if (ret < 0)
- {
- return ERROR;
- }
+ sprintf(strvtbl, "%p\n", vtbl);
+ argv[1] = strvtbl;
- /* Restore the original output */
+ /* Handle redirection of output via a file descriptor */
- /* nsh_undirect(save); */
+ if (redirect)
+ {
+ save = nsh_redirect(vtbl, fd);
}
- /* Return success if the command succeeded (or at least, starting of the
- * command task succeeded).
+ /* Then execute the command in "foreground" -- i.e., while the user waits
+ * for the next prompt.
+ */
+
+ ret = nsh_execute(argc, argv);
+
+ /* Restore the original output. Undirect will close the redirection
+ * file descriptor.
*/
- return OK;
+ if (redirect)
+ {
+ nsh_undirect(vtbl, save);
+ }
+
+ if (ret < 0)
+ {
+ return ERROR;
+ }
}
+ /* Return success if the command succeeded (or at least, starting of the
+ * command task succeeded).
+ */
+
+ return OK;
+
+errout:
+ if (redirect)
+ {
+ close(fd);
+ }
return ERROR;
}
diff --git a/nuttx/examples/nsh/nsh_netcmds.c b/nuttx/examples/nsh/nsh_netcmds.c
index 6c26584df..ee21ae154 100644
--- a/nuttx/examples/nsh/nsh_netcmds.c
+++ b/nuttx/examples/nsh/nsh_netcmds.c
@@ -1,7 +1,7 @@
/****************************************************************************
* examples/nsh/nsh_netcmds.c
*
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
* 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
+ * 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.
*
@@ -86,112 +86,112 @@
****************************************************************************/
#ifdef CONFIG_NET_STATISTICS
-static inline void uip_statistics(void *handle)
+static inline void uip_statistics(FAR struct nsh_vtbl_s *vtbl)
{
- nsh_output(handle, "uIP IP ");
+ nsh_output(vtbl, "uIP IP ");
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " TCP");
+ nsh_output(vtbl, " TCP");
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " UDP");
+ nsh_output(vtbl, " UDP");
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " ICMP");
+ nsh_output(vtbl, " ICMP");
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
/* Received packets */
- nsh_output(handle, "Received %04x",uip_stat.ip.recv);
+ nsh_output(vtbl, "Received %04x",uip_stat.ip.recv);
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " %04x",uip_stat.tcp.recv);
+ nsh_output(vtbl, " %04x",uip_stat.tcp.recv);
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " %04x",uip_stat.udp.recv);
+ nsh_output(vtbl, " %04x",uip_stat.udp.recv);
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " %04x",uip_stat.icmp.recv);
+ nsh_output(vtbl, " %04x",uip_stat.icmp.recv);
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
/* Dropped packets */
- nsh_output(handle, "Dropped %04x",uip_stat.ip.drop);
+ nsh_output(vtbl, "Dropped %04x",uip_stat.ip.drop);
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " %04x",uip_stat.tcp.drop);
+ nsh_output(vtbl, " %04x",uip_stat.tcp.drop);
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " %04x",uip_stat.udp.drop);
+ nsh_output(vtbl, " %04x",uip_stat.udp.drop);
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " %04x",uip_stat.icmp.drop);
+ nsh_output(vtbl, " %04x",uip_stat.icmp.drop);
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
- nsh_output(handle, " IP VHL: %04x HBL: %04x\n",
+ nsh_output(vtbl, " IP VHL: %04x HBL: %04x\n",
uip_stat.ip.vhlerr, uip_stat.ip.hblenerr);
- nsh_output(handle, " LBL: %04x Frg: %04x\n",
+ nsh_output(vtbl, " LBL: %04x Frg: %04x\n",
uip_stat.ip.lblenerr, uip_stat.ip.fragerr);
- nsh_output(handle, " Checksum %04x",uip_stat.ip.chkerr);
+ nsh_output(vtbl, " Checksum %04x",uip_stat.ip.chkerr);
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " %04x",uip_stat.tcp.chkerr);
+ nsh_output(vtbl, " %04x",uip_stat.tcp.chkerr);
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " %04x",uip_stat.udp.chkerr);
+ nsh_output(vtbl, " %04x",uip_stat.udp.chkerr);
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " ----");
+ nsh_output(vtbl, " ----");
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " TCP ACK: %04x SYN: %04x\n",
+ nsh_output(vtbl, " TCP ACK: %04x SYN: %04x\n",
uip_stat.tcp.ackerr, uip_stat.tcp.syndrop);
- nsh_output(handle, " RST: %04x %04x\n",
+ nsh_output(vtbl, " RST: %04x %04x\n",
uip_stat.tcp.rst, uip_stat.tcp.synrst);
#endif
- nsh_output(handle, " Type %04x",uip_stat.ip.protoerr);
+ nsh_output(vtbl, " Type %04x",uip_stat.ip.protoerr);
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " ----");
+ nsh_output(vtbl, " ----");
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " ----");
+ nsh_output(vtbl, " ----");
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " %04x",uip_stat.icmp.typeerr);
+ nsh_output(vtbl, " %04x",uip_stat.icmp.typeerr);
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
/* Sent packets */
- nsh_output(handle, "Sent ----",uip_stat.ip.sent);
+ nsh_output(vtbl, "Sent ----",uip_stat.ip.sent);
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " %04x",uip_stat.tcp.sent);
+ nsh_output(vtbl, " %04x",uip_stat.tcp.sent);
#endif
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " %04x",uip_stat.udp.sent);
+ nsh_output(vtbl, " %04x",uip_stat.udp.sent);
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " %04x",uip_stat.icmp.sent);
+ nsh_output(vtbl, " %04x",uip_stat.icmp.sent);
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
#ifdef CONFIG_NET_TCP
- nsh_output(handle, " Rexmit ---- %04x",uip_stat.tcp.rexmit);
+ nsh_output(vtbl, " Rexmit ---- %04x",uip_stat.tcp.rexmit);
#ifdef CONFIG_NET_UDP
- nsh_output(handle, " ----");
+ nsh_output(vtbl, " ----");
#endif
#ifdef CONFIG_NET_ICMP
- nsh_output(handle, " ----");
+ nsh_output(vtbl, " ----");
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
#endif
- nsh_output(handle, "\n");
+ nsh_output(vtbl, "\n");
}
#else
-# define uip_statistics(handle)
+# define uip_statistics(vtbl)
#endif
/****************************************************************************
@@ -200,15 +200,16 @@ static inline void uip_statistics(void *handle)
int ifconfig_callback(FAR struct uip_driver_s *dev, void *arg)
{
+ struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg;
struct in_addr addr;
- nsh_output(arg, "%s\tHWaddr %s\n", dev->d_ifname, ether_ntoa(&dev->d_mac));
+ nsh_output(vtbl, "%s\tHWaddr %s\n", dev->d_ifname, ether_ntoa(&dev->d_mac));
addr.s_addr = dev->d_ipaddr;
- nsh_output(arg, "\tIPaddr:%s ", inet_ntoa(addr));
+ nsh_output(vtbl, "\tIPaddr:%s ", inet_ntoa(addr));
addr.s_addr = dev->d_draddr;
- nsh_output(arg, "DRaddr:%s ", inet_ntoa(addr));
+ nsh_output(vtbl, "DRaddr:%s ", inet_ntoa(addr));
addr.s_addr = dev->d_netmask;
- nsh_output(arg, "Mask:%s\n\n", inet_ntoa(addr));
+ nsh_output(vtbl, "Mask:%s\n\n", inet_ntoa(addr));
return OK;
}
@@ -220,10 +221,10 @@ int ifconfig_callback(FAR struct uip_driver_s *dev, void *arg)
* Name: cmd_ifconfig
****************************************************************************/
-void cmd_ifconfig(FAR void *handle, int argc, char **argv)
+void cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- netdev_foreach(ifconfig_callback, handle);
- uip_statistics(handle);
+ netdev_foreach(ifconfig_callback, vtbl);
+ uip_statistics(vtbl);
}
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */
diff --git a/nuttx/examples/nsh/nsh_proccmds.c b/nuttx/examples/nsh/nsh_proccmds.c
index 4140c277d..3df84c62b 100644
--- a/nuttx/examples/nsh/nsh_proccmds.c
+++ b/nuttx/examples/nsh/nsh_proccmds.c
@@ -96,11 +96,12 @@ static const char *g_statenames[] =
static void ps_task(FAR _TCB *tcb, FAR void *arg)
{
+ struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg;
int i;
/* Show task status */
- nsh_output(arg, "%5d %3d %4s %7s%c%c %8s ",
+ nsh_output(vtbl, "%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 ",
@@ -110,13 +111,13 @@ static void ps_task(FAR _TCB *tcb, FAR void *arg)
/* Show task name and arguments */
- nsh_output(arg, "%s(", tcb->argv[0]);
+ nsh_output(vtbl, "%s(", tcb->argv[0]);
/* Special case 1st argument (no comma) */
if (tcb->argv[1])
{
- nsh_output(arg, "%p", tcb->argv[1]);
+ nsh_output(vtbl, "%p", tcb->argv[1]);
}
/* Then any additional arguments */
@@ -124,10 +125,10 @@ static void ps_task(FAR _TCB *tcb, FAR void *arg)
#if CONFIG_MAX_TASK_ARGS > 2
for (i = 2; i <= CONFIG_MAX_TASK_ARGS && tcb->argv[i]; i++)
{
- nsh_output(arg, ", %p", tcb->argv[i]);
+ nsh_output(vtbl, ", %p", tcb->argv[i]);
}
#endif
- nsh_output(arg, ")\n");
+ nsh_output(vtbl, ")\n");
}
/****************************************************************************
@@ -138,7 +139,7 @@ static void ps_task(FAR _TCB *tcb, FAR void *arg)
* Name: cmd_exec
****************************************************************************/
-void cmd_exec(FAR void *handle, int argc, char **argv)
+void cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
char *endptr;
long addr;
@@ -146,11 +147,11 @@ void cmd_exec(FAR void *handle, int argc, char **argv)
addr = strtol(argv[1], &endptr, 0);
if (!addr || endptr == argv[1] || *endptr != '\0')
{
- nsh_output(handle, g_fmtarginvalid, argv[0]);
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return;
}
- nsh_output(handle, "Calling %p\n", (exec_t)addr);
+ nsh_output(vtbl, "Calling %p\n", (exec_t)addr);
((exec_t)addr)();
}
@@ -158,10 +159,10 @@ void cmd_exec(FAR void *handle, int argc, char **argv)
* Name: cmd_ps
****************************************************************************/
-void cmd_ps(FAR void *handle, int argc, char **argv)
+void cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- nsh_output(handle, "PID PRI SCHD TYPE NP STATE NAME\n");
- sched_foreach(ps_task, handle);
+ nsh_output(vtbl, "PID PRI SCHD TYPE NP STATE NAME\n");
+ sched_foreach(ps_task, vtbl);
}
/****************************************************************************
@@ -169,7 +170,7 @@ void cmd_ps(FAR void *handle, int argc, char **argv)
****************************************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
-void cmd_sleep(FAR void *handle, int argc, char **argv)
+void cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
char *endptr;
long secs;
@@ -177,7 +178,7 @@ void cmd_sleep(FAR void *handle, int argc, char **argv)
secs = strtol(argv[1], &endptr, 0);
if (!secs || endptr == argv[1] || *endptr != '\0')
{
- nsh_output(handle, g_fmtarginvalid, argv[0]);
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return;
}
sleep(secs);
@@ -189,7 +190,7 @@ void cmd_sleep(FAR void *handle, int argc, char **argv)
****************************************************************************/
#ifndef CONFIG_DISABLE_SIGNALS
-void cmd_usleep(FAR void *handle, int argc, char **argv)
+void cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
char *endptr;
long usecs;
@@ -197,7 +198,7 @@ void cmd_usleep(FAR void *handle, int argc, char **argv)
usecs = strtol(argv[1], &endptr, 0);
if (!usecs || endptr == argv[1] || *endptr != '\0')
{
- nsh_output(handle, g_fmtarginvalid, argv[0]);
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
return;
}
usleep(usecs);
diff --git a/nuttx/examples/nsh/nsh_serial.c b/nuttx/examples/nsh/nsh_serial.c
index fee653266..c9abc88ed 100644
--- a/nuttx/examples/nsh/nsh_serial.c
+++ b/nuttx/examples/nsh/nsh_serial.c
@@ -42,6 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
#include <stdarg.h>
@@ -57,14 +58,25 @@
struct serial_s
{
- int ss_refs; /* Reference counts on the intance */
- char ss_line[CONFIG_EXAMPLES_NSH_LINELEN];
+ struct nsh_vtbl_s vtbl;
+ int ss_refs; /* Reference counts on the instance */
+ int ss_fd; /* Re-direct file descriptor */
+ FILE *ss_stream; /* Redirect file descriptor */
+ char ss_line[CONFIG_EXAMPLES_NSH_LINELEN];
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
+static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl);
+static void nsh_consoleaddref(FAR struct nsh_vtbl_s *vtbl);
+static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl);
+static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
+static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl);
+static FAR void *nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd);
+static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR void *direct);
+
/****************************************************************************
* Private Data
****************************************************************************/
@@ -86,125 +98,238 @@ static inline FAR struct serial_s *nsh_allocstruct(void)
struct serial_s *pstate = (struct serial_s *)malloc(sizeof(struct serial_s));
if (pstate)
{
- pstate->ss_refs = 1;
+ pstate->vtbl.clone = nsh_consoleclone;
+ pstate->vtbl.addref = nsh_consoleaddref;
+ pstate->vtbl.release = nsh_consolerelease;
+ pstate->vtbl.output = nsh_consoleoutput;
+ pstate->vtbl.linebuffer = nsh_consolelinebuffer;
+ pstate->vtbl.redirect = nsh_consoleredirect;
+ pstate->vtbl.undirect = nsh_consoleundirect;
+
+ pstate->ss_refs = 1;
+ pstate->ss_fd = 1;
+ pstate->ss_stream = stdout;
}
return pstate;
}
/****************************************************************************
- * Public Functions
+ * Name: nsh_openifnotopen
****************************************************************************/
+static int nsh_openifnotopen(struct serial_s *pstate)
+{
+ /* The stream is open in a lazy fashion. This is done because the file
+ * descriptor may be opened on a different task than the stream.
+ */
+
+ if (!pstate->ss_stream)
+ {
+ pstate->ss_stream = fdopen(pstate->ss_fd, "w");
+ if (!pstate->ss_stream)
+ {
+ return ERROR;
+ }
+ }
+ return 0;
+}
+
/****************************************************************************
- * Name: nsh_main
+ * Name: nsh_closeifnotclosed
****************************************************************************/
-int nsh_main(void)
+static void nsh_closeifnotclosed(struct serial_s *pstate)
{
- FAR struct serial_s *pstate = nsh_allocstruct();
-
- printf("NuttShell (NSH)\n");
- fflush(stdout);
-
- for (;;)
+ if (pstate->ss_stream == stdout)
{
- /* Display the prompt string */
-
- fputs(g_nshprompt, stdout);
fflush(stdout);
-
- /* Get the next line of input */
-
- if (fgets(pstate->ss_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
+ pstate->ss_fd = 1;
+ }
+ else
+ {
+ if (pstate->ss_stream)
{
- /* Parse process the command */
-
- (void)nsh_parse(pstate, pstate->ss_line);
- fflush(stdout);
+ fflush(pstate->ss_stream);
+ fclose(pstate->ss_stream);
+ }
+ else if (pstate->ss_fd >= 0 && pstate->ss_fd != 1)
+ {
+ close(pstate->ss_fd);
}
+
+ pstate->ss_fd = -1;
+ pstate->ss_stream = NULL;
}
}
/****************************************************************************
- * Name: nsh_output
+ * Name: nsh_consoleoutput
*
* Description:
- * Print a string to stdout.
+ * Print a string to the currently selected stream.
*
****************************************************************************/
-int nsh_output(FAR void *handle, const char *fmt, ...)
+static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...)
{
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
va_list ap;
int ret;
+
+ /* The stream is open in a lazy fashion. This is done because the file
+ * descriptor may be opened on a different task than the stream. The
+ * actual open will then occur with the first output from the new task.
+ */
+
+ if (nsh_openifnotopen(pstate) != 0)
+ {
+ return ERROR;
+ }
va_start(ap, fmt);
- ret = vfprintf(stdout, fmt, ap);
+ ret = vfprintf(pstate->ss_stream, fmt, ap);
va_end(ap);
return ret;
}
/****************************************************************************
- * Name: nsh_linebuffer
+ * Name: nsh_consolelinebuffer
*
* Description:
* Return a reference to the current line buffer
*
****************************************************************************/
-FAR char *nsh_linebuffer(FAR void *handle)
+static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl)
{
- FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
return pstate->ss_line;
}
/****************************************************************************
- * Name: nsh_clone
+ * Name: nsh_consoleclone
*
* Description:
- * Make an independent copy of the handle
+ * Make an independent copy of the vtbl
*
****************************************************************************/
-FAR void *nsh_clone(FAR void *handle)
+static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl)
{
- return nsh_allocstruct();
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
+ FAR struct serial_s *pclone = nsh_allocstruct();
+ pclone->ss_fd = pstate->ss_fd;
+ pclone->ss_stream = NULL;
+ return &pclone->vtbl;
}
/****************************************************************************
- * Name: nsh_addref
+ * Name: nsh_consoleaddref
*
* Description:
- * Increment the reference count on the handle.
+ * Increment the reference count on the vtbl.
*
****************************************************************************/
-void nsh_addref(FAR void *handle)
+static void nsh_consoleaddref(FAR struct nsh_vtbl_s *vtbl)
{
- FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
pstate->ss_refs++;
}
/****************************************************************************
- * Name: nsh_release
+ * Name: nsh_consolerelease
*
* Description:
- * Decrement the reference count on the handle, releasing it when the count
+ * Decrement the reference count on the vtbl, releasing it when the count
* decrements to zero.
*
****************************************************************************/
-void nsh_release(FAR void *handle)
+static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl)
{
- FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
if (pstate->ss_refs > 1)
{
pstate->ss_refs--;
}
else
{
- free(handle);
+ nsh_closeifnotclosed(pstate);
+ free(vtbl);
+ }
+}
+
+/****************************************************************************
+ * Name: nsh_consoleredirect
+ *
+ * Description:
+ * Set up for redirected output
+ *
+ ****************************************************************************/
+
+static FAR void *nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd)
+{
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
+ void *ret;
+
+ (void)nsh_openifnotopen(pstate);
+ ret = pstate->ss_stream;
+ fflush(pstate->ss_stream);
+
+ pstate->ss_fd = fd;
+ pstate->ss_stream = NULL;
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nsh_consoleredirect
+ *
+ * Description:
+ * Set up for redirected output
+ *
+ ****************************************************************************/
+
+static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR void *direct)
+{
+ FAR struct serial_s *pstate = (FAR struct serial_s *)vtbl;
+ nsh_closeifnotclosed(pstate);
+ pstate->ss_fd = -1;
+ pstate->ss_stream = (FILE*)direct;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_main
+ ****************************************************************************/
+
+int nsh_consolemain(int argc, char *argv[])
+{
+ FAR struct serial_s *pstate = nsh_allocstruct();
+
+ printf("NuttShell (NSH)\n");
+ fflush(pstate->ss_stream);
+
+ for (;;)
+ {
+ /* Display the prompt string */
+
+ fputs(g_nshprompt, pstate->ss_stream);
+ fflush(pstate->ss_stream);
+
+ /* Get the next line of input */
+
+ if (fgets(pstate->ss_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
+ {
+ /* Parse process the command */
+
+ (void)nsh_parse(&pstate->vtbl, pstate->ss_line);
+ fflush(pstate->ss_stream);
+ }
}
}
@@ -216,7 +341,7 @@ void nsh_release(FAR void *handle)
*
****************************************************************************/
-void cmd_exit(void *handle, int argc, char **argv)
+void cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
exit(0);
}
diff --git a/nuttx/examples/nsh/nsh_telnetd.c b/nuttx/examples/nsh/nsh_telnetd.c
index 3f1c1374d..551509d74 100644
--- a/nuttx/examples/nsh/nsh_telnetd.c
+++ b/nuttx/examples/nsh/nsh_telnetd.c
@@ -85,6 +85,7 @@
struct telnetd_s
{
+ struct nsh_vtbl_s vtbl;
int tn_sockfd;
uint16 tn_sndlen;
uint8 tn_bufndx;
@@ -94,6 +95,18 @@ struct telnetd_s
};
/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static FAR struct nsh_vtbl_s *nsh_telnetclone(FAR struct nsh_vtbl_s *vtbl);
+static void nsh_telnetaddref(FAR struct nsh_vtbl_s *vtbl);
+static void nsh_telnetrelease(FAR struct nsh_vtbl_s *vtbl);
+static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...);
+static FAR char *nsh_telnetlinebuffer(FAR struct nsh_vtbl_s *vtbl);
+static FAR void *nsh_telnetredirect(FAR struct nsh_vtbl_s *vtbl, int fd);
+static void nsh_telnetundirect(FAR struct nsh_vtbl_s *vtbl, FAR void *direct);
+
+/****************************************************************************
* Private Functions
****************************************************************************/
@@ -148,6 +161,27 @@ static void nsh_dumpbuffer(const char *msg, const char *buffer, ssize_t nbytes)
#endif
/****************************************************************************
+ * Name: nsh_allocstruct
+ ****************************************************************************/
+
+static inline FAR struct telnetd_s *nsh_allocstruct(void)
+{
+ struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s));
+ if (pstate)
+ {
+ memset(pstate, 0, sizeof(struct telnetd_s));
+ pstate->vtbl.clone = nsh_telnetclone;
+ pstate->vtbl.addref = nsh_telnetaddref;
+ pstate->vtbl.release = nsh_telnetrelease;
+ pstate->vtbl.output = nsh_telnetoutput;
+ pstate->vtbl.linebuffer = nsh_telnetlinebuffer;
+ pstate->vtbl.redirect = nsh_telnetredirect;
+ pstate->vtbl.undirect = nsh_telnetundirect;
+ }
+ return pstate;
+}
+
+/****************************************************************************
* Name: nsh_putchar
*
* Description:
@@ -178,7 +212,7 @@ static void nsh_putchar(struct telnetd_s *pstate, uint8 ch)
}
nsh_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd));
- nsh_parse((void*)pstate, pstate->tn_cmd);
+ nsh_parse(&pstate->vtbl, pstate->tn_cmd);
pstate->tn_bufndx = 0;
}
else
@@ -340,7 +374,7 @@ static int nsh_receive(struct telnetd_s *pstate, size_t len)
static void *nsh_connection(void *arg)
{
- struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s));
+ struct telnetd_s *pstate = nsh_allocstruct();
int sockfd = (int)arg;
int ret = ERROR;
@@ -352,13 +386,12 @@ static void *nsh_connection(void *arg)
{
/* Initialize the thread state structure */
- memset(pstate, 0, sizeof(struct telnetd_s));
pstate->tn_sockfd = sockfd;
pstate->tn_state = STATE_NORMAL;
/* Output a greeting */
- nsh_output(pstate, "NuttShell (NSH)\n");
+ nsh_output(&pstate->vtbl, "NuttShell (NSH)\n");
/* Loop processing each TELNET command */
@@ -366,7 +399,7 @@ static void *nsh_connection(void *arg)
{
/* Display the prompt string */
- nsh_output(pstate, g_nshprompt);
+ nsh_output(&pstate->vtbl, g_nshprompt);
nsh_flush(pstate);
/* Read a buffer of data from the TELNET client */
@@ -397,6 +430,79 @@ static void *nsh_connection(void *arg)
}
/****************************************************************************
+ * Name: nsh_telnetoutput
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+static int nsh_telnetoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...)
+{
+ struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
+ int nbytes = pstate->tn_sndlen;
+ int len;
+ va_list ap;
+
+ /* Put the new info into the buffer. Here we are counting on the fact that
+ * no output strings will exceed CONFIG_EXAMPLES_NSH_LINELEN!
+ */
+
+ va_start(ap, fmt);
+ vsnprintf(&pstate->tn_iobuffer[nbytes],
+ (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 1) - nbytes, fmt, ap);
+ va_end(ap);
+
+ /* Get the size of the new string just added and the total size of
+ * buffered data
+ */
+
+ len = strlen(&pstate->tn_iobuffer[nbytes]);
+ nbytes += len;
+
+ /* Expand any terminating \n to \r\n */
+
+ if (nbytes < (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 2) &&
+ pstate->tn_iobuffer[nbytes-1] == '\n')
+ {
+ pstate->tn_iobuffer[nbytes-1] = ISO_cr;
+ pstate->tn_iobuffer[nbytes] = ISO_nl;
+ pstate->tn_iobuffer[nbytes+1] = '\0';
+ nbytes++;
+ }
+ pstate->tn_sndlen = nbytes;
+
+ /* Flush to the network if the buffer does not have room for one more
+ * maximum length string.
+ */
+
+ if (nbytes > CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - CONFIG_EXAMPLES_NSH_LINELEN)
+ {
+ nsh_flush(pstate);
+ }
+
+ return len;
+}
+
+/****************************************************************************
+ * Name: nsh_telnetlinebuffer
+ *
+ * Description:
+ * Return a reference to the current line buffer
+ *
+ ****************************************************************************/
+
+static FAR char *nsh_telnetlinebuffer(FAR struct nsh_vtbl_s *vtbl)
+{
+ struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
+ return pstate->tn_cmd;
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -409,7 +515,7 @@ static void *nsh_connection(void *arg)
*
****************************************************************************/
-int nsh_main(void)
+int nsh_telnetmain(int argc, char *argv[])
{
struct in_addr addr;
#if defined(CONFIG_EXAMPLES_NSH_DHCPC) || defined(CONFIG_EXAMPLES_NSH_NOMAC)
@@ -492,79 +598,6 @@ int nsh_main(void)
}
/****************************************************************************
- * Name: nsh_output
- *
- * 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_output(FAR void *handle, const char *fmt, ...)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
- int nbytes = pstate->tn_sndlen;
- int len;
- va_list ap;
-
- /* Put the new info into the buffer. Here we are counting on the fact that
- * no output strings will exceed CONFIG_EXAMPLES_NSH_LINELEN!
- */
-
- va_start(ap, fmt);
- vsnprintf(&pstate->tn_iobuffer[nbytes],
- (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 1) - nbytes, fmt, ap);
- va_end(ap);
-
- /* Get the size of the new string just added and the total size of
- * buffered data
- */
-
- len = strlen(&pstate->tn_iobuffer[nbytes]);
- nbytes += len;
-
- /* Expand any terminating \n to \r\n */
-
- if (nbytes < (CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - 2) &&
- pstate->tn_iobuffer[nbytes-1] == '\n')
- {
- pstate->tn_iobuffer[nbytes-1] = ISO_cr;
- pstate->tn_iobuffer[nbytes] = ISO_nl;
- pstate->tn_iobuffer[nbytes+1] = '\0';
- nbytes++;
- }
- pstate->tn_sndlen = nbytes;
-
- /* Flush to the network if the buffer does not have room for one more
- * maximum length string.
- */
-
- if (nbytes > CONFIG_EXAMPLES_NSH_IOBUFFER_SIZE - CONFIG_EXAMPLES_NSH_LINELEN)
- {
- nsh_flush(pstate);
- }
-
- return len;
-}
-
-/****************************************************************************
- * Name: nsh_linebuffer
- *
- * Description:
- * Return a reference to the current line buffer
- *
- ****************************************************************************/
-
-FAR char *nsh_linebuffer(FAR void *handle)
-{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
- return pstate->tn_cmd;
-}
-
-/****************************************************************************
* Name: cmd_exit
*
* Description:
@@ -572,9 +605,9 @@ FAR char *nsh_linebuffer(FAR void *handle)
*
****************************************************************************/
-void cmd_exit(void *handle, int argc, char **argv)
+void cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
- struct telnetd_s *pstate = (struct telnetd_s *)handle;
+ struct telnetd_s *pstate = (struct telnetd_s *)vtbl;
pstate->tn_state = STATE_CLOSE;
}