From 9f2b12c2529e0fbe02693c35a82bd35168637c23 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 30 Sep 2013 11:34:04 -0600 Subject: Changes to NSH and readline to permit NSH to work on a platform with no file system --- apps/nshlib/Makefile | 13 ++-- apps/nshlib/nsh.h | 8 +++ apps/nshlib/nsh_builtin.c | 6 +- apps/nshlib/nsh_console.c | 53 ++++++++++++--- apps/nshlib/nsh_console.h | 28 ++++---- apps/nshlib/nsh_parse.c | 27 +++++++- apps/nshlib/nsh_session.c | 4 +- apps/nshlib/nsh_stdsession.c | 152 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 261 insertions(+), 30 deletions(-) create mode 100644 apps/nshlib/nsh_stdsession.c (limited to 'apps/nshlib') diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile index 76cdac40d..a1586bb00 100644 --- a/apps/nshlib/Makefile +++ b/apps/nshlib/Makefile @@ -40,9 +40,14 @@ include $(APPDIR)/Make.defs # NSH Library ASRCS = -CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_session.c -CSRCS += nsh_fscmds.c nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c -CSRCS += nsh_dbgcmds.c +CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_fscmds.c +CSRCS += nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c nsh_dbgcmds.c + +ifeq ($(CONFIG_NFILE_STREAMS),0) +CSRCS += nsh_stdsession.c +else +CSRCS += nsh_session.c +endif ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) CSRCS += nsh_builtin.c @@ -105,7 +110,7 @@ endif endif ROOTDEPPATH = --dep-path . -VPATH = +VPATH = # Build targets diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h index 9f1bb40fe..bcad42b1d 100644 --- a/apps/nshlib/nsh.h +++ b/apps/nshlib/nsh.h @@ -68,6 +68,12 @@ # endif #endif +#if CONFIG_NFILE_STREAMS == 0 +# undef CONFIG_NSH_TELNET +# undef CONFIG_NSH_FILE_APPS +# undef CONFIG_NSH_TELNET +#endif + /* Telnetd requires networking support */ #ifndef CONFIG_NET @@ -441,7 +447,9 @@ struct nsh_parser_s #ifndef CONFIG_NSH_DISABLEBG bool np_bg; /* true: The last command executed in background */ #endif +#if CONFIG_NFILE_STREAMS > 0 bool np_redirect; /* true: Output from the last command was re-directed */ +#endif bool np_fail; /* true: The last command failed */ #ifndef CONFIG_NSH_DISABLESCRIPT uint8_t np_ndx; /* Current index into np_st[] */ diff --git a/apps/nshlib/nsh_builtin.c b/apps/nshlib/nsh_builtin.c index 0819377de..59e54ae85 100644 --- a/apps/nshlib/nsh_builtin.c +++ b/apps/nshlib/nsh_builtin.c @@ -131,7 +131,7 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, { /* The application was successfully started with pre-emption disabled. * In the simplest cases, the application will not have run because the - * the scheduler is locked. But in the case where I/O was redirected, a + * the scheduler is locked. But in the case where I/O was redirected, a * proxy task ran and broke our lock. As result, the application may * have aso ran if its priority was higher than than the priority of * this thread. @@ -166,7 +166,7 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, * do so. * * Also, if CONFIG_SCHED_HAVE_PARENT is defined waitpid() might fail - * even if task is still active: If the I/O was re-directed by a + * even if task is still active: If the I/O was re-directed by a * proxy task, then the ask is a child of the proxy, and not this * task. waitpid() fails with ECHILD in either case. */ @@ -200,7 +200,7 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, else { /* We can't return the exact status (nsh has nowhere to put it) - * so just pass back zero/nonzero in a fashion that doesn't look + * so just pass back zero/nonzero in a fashion that doesn't look * like an error. */ diff --git a/apps/nshlib/nsh_console.c b/apps/nshlib/nsh_console.c index 1b8f5f6ac..410abc19d 100644 --- a/apps/nshlib/nsh_console.c +++ b/apps/nshlib/nsh_console.c @@ -1,7 +1,7 @@ /**************************************************************************** - * apps/nshlib/nsh_serial.c + * apps/nshlib/nsh_console.c * - * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -61,11 +61,13 @@ * Private Types ****************************************************************************/ +#if CONFIG_NFILE_STREAMS > 0 struct serialsave_s { int cn_outfd; /* Re-directed output file descriptor */ FILE *cn_outstream; /* Re-directed output stream */ }; +#endif /**************************************************************************** * Private Function Prototypes @@ -80,10 +82,14 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, FAR const char *fmt, ...); static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl); + +#if CONFIG_NFILE_DESCRIPTORS > 0 static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); +#endif + static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus) noreturn_function; @@ -103,6 +109,7 @@ static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus) * Name: nsh_openifnotopen ****************************************************************************/ +#if CONFIG_NFILE_DESCRIPTORS > 0 static int nsh_openifnotopen(struct console_stdio_s *pstate) { /* The stream is open in a lazy fashion. This is done because the file @@ -117,8 +124,10 @@ static int nsh_openifnotopen(struct console_stdio_s *pstate) return ERROR; } } + return 0; } +#endif /**************************************************************************** * Name: nsh_closeifnotclosed @@ -128,6 +137,7 @@ static int nsh_openifnotopen(struct console_stdio_s *pstate) * ****************************************************************************/ +#if CONFIG_NFILE_STREAMS > 0 static void nsh_closeifnotclosed(struct console_stdio_s *pstate) { if (pstate->cn_outstream == OUTSTREAM(pstate)) @@ -151,6 +161,7 @@ static void nsh_closeifnotclosed(struct console_stdio_s *pstate) pstate->cn_outstream = NULL; } } +#endif /**************************************************************************** * Name: nsh_consolewrite @@ -167,6 +178,7 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buf FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; ssize_t ret; +#if CONFIG_NFILE_DESCRIPTORS > 0 /* 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. @@ -185,6 +197,10 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buf dbg("[%d] Failed to send buffer: %d\n", pstate->cn_outfd, errno); } return ret; +#else + printf("%s", buffer); + return nbytes; +#endif } /**************************************************************************** @@ -197,9 +213,10 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl, FAR const void *buf static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...) { +#if CONFIG_NFILE_DESCRIPTORS > 0 FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; va_list ap; - int ret; + 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 @@ -210,12 +227,21 @@ static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...) { return ERROR; } - + va_start(ap, fmt); ret = vfprintf(pstate->cn_outstream, fmt, ap); va_end(ap); - + return ret; +#else + char dest[64 * 16]; + + va_start(ap, fmt); + vsprintf(dest, fmt, ap); + va_end(ap); + + return printf(dest); +#endif } /**************************************************************************** @@ -260,6 +286,7 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) { FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; +#if CONFIG_NFILE_DESCRIPTORS > 0 /* Close the output stream */ nsh_closeifnotclosed(pstate); @@ -268,6 +295,7 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) #ifdef CONFIG_NSH_CONDEV (void)fclose(pstate->cn_constream); +#endif #endif /* Then release the vtable container */ @@ -292,7 +320,7 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) * * nsh_consolerelease() will perform the clean-up when the clone is * destroyed. - * + * * 2) Redirected foreground commands of the form: command > xyz.txt * * In this case: @@ -305,9 +333,10 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) * ****************************************************************************/ +#if CONFIG_NFILE_DESCRIPTORS > 0 static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save) { - FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; + FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save; /* Case 1: Redirected foreground commands */ @@ -321,7 +350,7 @@ static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t if (pstate->cn_outstream) { - fflush(pstate->cn_outstream); + fflush(pstate->cn_outstream); } /* Save the current fd and stream values. These will be restored @@ -346,6 +375,7 @@ static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t pstate->cn_outfd = fd; pstate->cn_outstream = NULL; } +#endif /**************************************************************************** * Name: nsh_consoleundirect @@ -355,6 +385,7 @@ static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t * ****************************************************************************/ +#if CONFIG_NFILE_DESCRIPTORS > 0 static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save) { FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; @@ -364,6 +395,7 @@ static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save) pstate->cn_outfd = ssave->cn_outfd; pstate->cn_outstream = ssave->cn_outstream; } +#endif /**************************************************************************** * Name: nsh_consoleexit @@ -403,9 +435,11 @@ FAR struct console_stdio_s *nsh_newconsole(void) pstate->cn_vtbl.write = nsh_consolewrite; pstate->cn_vtbl.output = nsh_consoleoutput; pstate->cn_vtbl.linebuffer = nsh_consolelinebuffer; + pstate->cn_vtbl.exit = nsh_consoleexit; + +#if CONFIG_NFILE_STREAMS > 0 pstate->cn_vtbl.redirect = nsh_consoleredirect; pstate->cn_vtbl.undirect = nsh_consoleundirect; - pstate->cn_vtbl.exit = nsh_consoleexit; /* (Re-) open the console input device */ @@ -432,6 +466,7 @@ FAR struct console_stdio_s *nsh_newconsole(void) pstate->cn_outfd = OUTFD(pstate); pstate->cn_outstream = OUTSTREAM(pstate); +#endif } return pstate; } diff --git a/apps/nshlib/nsh_console.h b/apps/nshlib/nsh_console.h index 4dc2938cb..73bab493b 100644 --- a/apps/nshlib/nsh_console.h +++ b/apps/nshlib/nsh_console.h @@ -1,7 +1,7 @@ /**************************************************************************** * apps/nshlib/nsh_console.h * - * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -74,16 +74,18 @@ /* Are we using the NuttX console for I/O? Or some other character device? */ -#ifdef CONFIG_NSH_CONDEV -# define INFD(p) ((p)->cn_confd) -# define INSTREAM(p) ((p)->cn_constream) -# define OUTFD(p) ((p)->cn_confd) -# define OUTSTREAM(p) ((p)->cn_constream) -#else -# define INFD(p) 0 -# define INSTREAM(p) stdin -# define OUTFD(p) 1 -# define OUTSTREAM(p) stdout +#if CONFIG_NFILE_STREAMS > 0 +# ifdef CONFIG_NSH_CONDEV +# define INFD(p) ((p)->cn_confd) +# define INSTREAM(p) ((p)->cn_constream) +# define OUTFD(p) ((p)->cn_confd) +# define OUTSTREAM(p) ((p)->cn_constream) +# else +# define INFD(p) 0 +# define INSTREAM(p) stdin +# define OUTFD(p) 1 +# define OUTSTREAM(p) stdout +# endif #endif /**************************************************************************** @@ -107,8 +109,10 @@ struct nsh_vtbl_s ssize_t (*write)(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer, size_t nbytes); int (*output)(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...); FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl); +#if CONFIG_NFILE_DESCRIPTORS > 0 void (*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save); void (*undirect)(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save); +#endif void (*exit)(FAR struct nsh_vtbl_s *vtbl, int exitstatus) noreturn_function; /* Parser state data */ @@ -128,6 +132,7 @@ struct console_stdio_s /* NSH input/output streams */ +#if CONFIG_NFILE_STREAMS > 0 #ifdef CONFIG_NSH_CONDEV int cn_confd; /* Console I/O file descriptor */ #endif @@ -136,6 +141,7 @@ struct console_stdio_s FILE *cn_constream; /* Console I/O stream (possibly redirected) */ #endif FILE *cn_outstream; /* Output stream */ +#endif /* Line input buffer */ diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c index 3f17149f5..d449bf61e 100644 --- a/apps/nshlib/nsh_parse.c +++ b/apps/nshlib/nsh_parse.c @@ -821,6 +821,7 @@ static void nsh_releaseargs(struct cmdarg_s *arg) FAR struct nsh_vtbl_s *vtbl = arg->vtbl; int i; +#if CONFIG_NFILE_STREAMS > 0 /* If the output was redirected, then file descriptor should * be closed. The created task has its one, independent copy of * the file descriptor @@ -830,6 +831,7 @@ static void nsh_releaseargs(struct cmdarg_s *arg) { (void)close(arg->fd); } +#endif /* Released the cloned vtbl instance */ @@ -1297,9 +1299,11 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) FAR char *argv[MAX_ARGV_ENTRIES]; FAR char *saveptr; FAR char *cmd; +#if CONFIG_NFILE_STREAMS > 0 FAR char *redirfile = NULL; - int fd = -1; int oflags = 0; +#endif + int fd = -1; int argc; int ret; @@ -1309,7 +1313,9 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) #ifndef CONFIG_NSH_DISABLEBG vtbl->np.np_bg = false; #endif +#if CONFIG_NFILE_STREAMS > 0 vtbl->np.np_redirect = false; +#endif /* Parse out the command at the beginning of the line */ @@ -1388,6 +1394,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) } #endif +#if CONFIG_NFILE_STREAMS > 0 /* Check if the output was re-directed using > or >> */ if (argc > 2) @@ -1412,6 +1419,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) argc -= 2; } } +#endif /* Check if the maximum number of arguments was exceeded */ @@ -1480,7 +1488,11 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) */ #if defined(CONFIG_NSH_BUILTIN_APPS) && (!defined(CONFIG_NSH_FILE_APPS) || !defined(CONFIG_FS_BINFS)) +#if CONFIG_NFILE_STREAMS > 0 ret = nsh_builtin(vtbl, argv[0], argv, redirfile, oflags); +#else + ret = nsh_builtin(vtbl, argv[0], argv, NULL, 0); +#endif if (ret >= 0) { /* nsh_builtin() returned 0 or 1. This means that the builtin @@ -1488,12 +1500,14 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) * successfully). So certainly it is not an NSH command. */ +#if CONFIG_NFILE_STREAMS > 0 /* Free the redirected output file path */ if (redirfile) { nsh_freefullpath(redirfile); } +#endif /* Save the result: success if 0; failure if 1 */ @@ -1506,6 +1520,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) #endif +#if CONFIG_NFILE_STREAMS > 0 /* Redirected output? */ if (vtbl->np.np_redirect) @@ -1526,6 +1541,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) goto errout; } } +#endif /* Handle the case where the command is executed in background. * However is app is to be started as builtin new process will @@ -1561,12 +1577,14 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) goto errout_with_redirect; } +#if CONFIG_NFILE_STREAMS > 0 /* Handle redirection of output via a file descriptor */ if (vtbl->np.np_redirect) { (void)nsh_redirect(bkgvtbl, fd, NULL); } +#endif /* Get the execution priority of this task */ @@ -1634,12 +1652,14 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) { uint8_t save[SAVE_SIZE]; +#if CONFIG_NFILE_STREAMS > 0 /* Handle redirection of output via a file descriptor */ if (vtbl->np.np_redirect) { nsh_redirect(vtbl, fd, save); } +#endif /* Then execute the command in "foreground" -- i.e., while the user waits * for the next prompt. nsh_execute will return: @@ -1650,6 +1670,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) ret = nsh_execute(vtbl, argc, argv); +#if CONFIG_NFILE_STREAMS > 0 /* Restore the original output. Undirect will close the redirection * file descriptor. */ @@ -1658,6 +1679,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) { nsh_undirect(vtbl, save); } +#endif /* Mark errors so that it is possible to test for non-zero return values * in nsh scripts. @@ -1677,11 +1699,14 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline) #ifndef CONFIG_NSH_DISABLEBG errout_with_redirect: +#if CONFIG_NFILE_STREAMS > 0 if (vtbl->np.np_redirect) { close(fd); } #endif +#endif + errout: return nsh_saveresult(vtbl, true); } diff --git a/apps/nshlib/nsh_session.c b/apps/nshlib/nsh_session.c index 0c5249672..2272b1e30 100644 --- a/apps/nshlib/nsh_session.c +++ b/apps/nshlib/nsh_session.c @@ -94,7 +94,7 @@ * * Returned Values: * EXIT_SUCESS or EXIT_FAILURE is returned. - * + * ****************************************************************************/ int nsh_session(FAR struct console_stdio_s *pstate) @@ -150,7 +150,7 @@ int nsh_session(FAR struct console_stdio_s *pstate) else { - fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_session", + fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_session", "readline", NSH_ERRNO_OF(-ret)); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/apps/nshlib/nsh_stdsession.c b/apps/nshlib/nsh_stdsession.c new file mode 100644 index 000000000..11fae7db7 --- /dev/null +++ b/apps/nshlib/nsh_stdsession.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * apps/nshlib/nsh_stdsession.c + * + * Copyright (C) 2013 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 "nsh.h" +#include "nsh_console.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nsh_session + * + * Description: + * This is the common session logic or an NSH session that uses only stdin + * and stdout. + * + * This function: + * - Executes the NSH logic script + * - Presents a greeting + * - Then provides a prompt then gets and processes the command line. + * - This continues until an error occurs, then the session returns. + * + * Input Parameters: + * pstate - Abstracts the underlying session. + * + * Returned Values: + * EXIT_SUCESS only + * + ****************************************************************************/ + +int nsh_session(FAR struct console_stdio_s *pstate) +{ + int ret; + + DEBUGASSERT(pstate); + + /* Present a greeting */ + + printf("%s", g_nshgreeting); + + /* Then enter the command line parsing loop */ + + for (;;) + { + /* For the case of debugging the USB console... dump collected USB trace data */ + +#ifdef CONFIG_NSH_USBDEV_TRACE + nsh_usbtrace(); +#endif + + /* Display the prompt string */ + + printf("%s", g_nshprompt); + + /* Get the next line of input. readline() returns EOF on end-of-file + * or any read failure. + */ + + ret = std_readline(pstate->cn_line, CONFIG_NSH_LINELEN); + if (ret != EOF) + { + /* Parse process the command */ + + (void)nsh_parse(&pstate->cn_vtbl, pstate->cn_line); + } + + /* Readline normally returns the number of characters read, + * but will return EOF on end of file or if an error occurs. + * EOF will cause the session to terminate. + */ + + else + { + printf(g_fmtcmdfailed, "nsh_session", "readline", NSH_ERRNO_OF(-ret)); + return EXIT_SUCCESS; + } + } + + /* We do not get here, but this is necessary to keep some compilers happy. + * But others will complain that this code is not reachable. + */ + + return EXIT_SUCCESS; +} -- cgit v1.2.3