nsh: Accept the command line arguments like sh

Usage: nsh [<script-path>|-c <command>]

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Change-Id: Ifb76b27e7fd09d26b1f6e48c391fed0972018041
This commit is contained in:
Xiang Xiao 2020-08-17 18:28:50 +08:00 committed by David Sidrane
parent 78e8090842
commit 9d80399bd5
14 changed files with 203 additions and 182 deletions

View File

@ -191,7 +191,7 @@ static int nxterm_task(int argc, char **argv)
/* If the console front end is selected, then run it on this thread */
#ifdef CONFIG_NSH_CONSOLE
nsh_consolemain(0, NULL);
nsh_consolemain(argc, argv);
#endif
printf("nxterm_task: Unlinking the NX console device\n");

View File

@ -384,7 +384,7 @@ int main(int argc, FAR char *argv[])
pid = task_create("NSH Console", CONFIG_EXAMPLES_PTYTEST_DAEMONPRIO,
CONFIG_EXAMPLES_PTYTEST_STACKSIZE, nsh_consolemain,
NULL);
argv);
if (pid < 0)
{
/* Can't do output because stdout and stderr are redirected */

View File

@ -48,6 +48,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Tab completion cannot be supported if there is no console echo */
#ifndef CONFIG_READLINE_ECHO

View File

@ -850,7 +850,8 @@ int nsh_loginscript(FAR struct nsh_vtbl_s *vtbl);
/* Basic session and message handling */
struct console_stdio_s;
int nsh_session(FAR struct console_stdio_s *pstate, bool login);
int nsh_session(FAR struct console_stdio_s *pstate,
bool login, int argc, FAR char *argv[]);
int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline);
/****************************************************************************

View File

@ -325,7 +325,7 @@ int nsh_consolemain(int argc, FAR char *argv[])
/* Execute the session */
nsh_session(pstate, true);
nsh_session(pstate, true, argc, argv);
/* We lost the connection. Wait for the keyboard to
* be re-connected.

View File

@ -1,7 +1,8 @@
/****************************************************************************
* apps/nshlib/nsh_console.c
*
* Copyright (C) 2007-2009, 2011-2013, 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2013, 2015 Gregory Nutt.
* All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -180,9 +181,9 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl,
*/
if (nsh_openifnotopen(pstate) != 0)
{
return (ssize_t)ERROR;
}
{
return ERROR;
}
/* Write the data to the output stream */
@ -221,9 +222,9 @@ static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl,
*/
if (nsh_openifnotopen(pstate) != 0)
{
return ERROR;
}
{
return ERROR;
}
va_start(ap, fmt);
ret = vfprintf(pstate->cn_outstream, fmt, ap);
@ -253,9 +254,9 @@ static int nsh_erroroutput(FAR struct nsh_vtbl_s *vtbl,
*/
if (nsh_openifnotopen(pstate) != 0)
{
return ERROR;
}
{
return ERROR;
}
va_start(ap, fmt);
ret = vfprintf(pstate->cn_errstream, fmt, ap);

View File

@ -52,6 +52,7 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Method access macros */
#define nsh_clone(v) (v)->clone(v)
@ -70,8 +71,9 @@
# define nsh_output vtbl->output
#endif
/* Size of info to be saved in call to nsh_redirect */
/* See struct serialsave_s in nsh_console.c */
/* Size of info to be saved in call to nsh_redirect
* See struct serialsave_s in nsh_console.c
*/
#define SAVE_SIZE (2 * sizeof(int) + 2 * sizeof(FILE*))
@ -107,6 +109,7 @@
/****************************************************************************
* Public Types
****************************************************************************/
/* This describes a generic console front-end */
struct nsh_vtbl_s
@ -129,10 +132,10 @@ struct nsh_vtbl_s
FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl);
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);
void (*exit)(FAR struct nsh_vtbl_s *vtbl, int exitstatus) noreturn_function;
void (*exit)(FAR struct nsh_vtbl_s *vtbl, int status) noreturn_function;
#ifdef NSH_HAVE_IOBUFFER
/* Common buffer for file I/O. */
/* Common buffer for file I/O. */
char iobuffer[IOBUFFERSIZE];
#endif

View File

@ -112,7 +112,7 @@ int nsh_consolemain(int argc, FAR char *argv[])
/* Execute the session */
ret = nsh_session(pstate, true);
ret = nsh_session(pstate, true, argc, argv);
/* Exit upon return */

View File

@ -42,6 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef CONFIG_NSH_CLE
# include "system/cle.h"
@ -79,10 +80,11 @@
*
****************************************************************************/
int nsh_session(FAR struct console_stdio_s *pstate, bool login)
int nsh_session(FAR struct console_stdio_s *pstate,
bool login, int argc, FAR char *argv[])
{
FAR struct nsh_vtbl_s *vtbl;
int ret;
int ret = EXIT_FAILURE;
DEBUGASSERT(pstate);
vtbl = &pstate->cn_vtbl;
@ -126,70 +128,92 @@ int nsh_session(FAR struct console_stdio_s *pstate, bool login)
#endif
}
/* Then enter the command line parsing loop */
for (; ; )
if (argc < 2)
{
/* For the case of debugging the USB console...
* dump collected USB trace data
*/
/* Then enter the command line parsing loop */
#ifdef CONFIG_NSH_USBDEV_TRACE
nsh_usbtrace();
#endif
/* Get the next line of input. readline() returns EOF on end-of-file
* or any read failure.
*/
#ifdef CONFIG_NSH_CLE
/* cle() normally returns the number of characters read, but will
* return a negated errno value on end of file or if an error occurs.
* Either will cause the session to terminate.
*/
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
INSTREAM(pstate), OUTSTREAM(pstate));
if (ret < 0)
for (; ; )
{
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
"cle", NSH_ERRNO_OF(-ret));
continue;
}
#else
/* Display the prompt string */
fputs(g_nshprompt, pstate->cn_outstream);
fflush(pstate->cn_outstream);
/* 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.
*/
ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
INSTREAM(pstate), OUTSTREAM(pstate));
if (ret == EOF)
{
/* NOTE: readline() does not set the errno variable, but perhaps we
* will be lucky and it will still be valid.
/* For the case of debugging the USB console...
* dump collected USB trace data
*/
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
"readline", NSH_ERRNO);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
#ifdef CONFIG_NSH_USBDEV_TRACE
nsh_usbtrace();
#endif
/* Get the next line of input. readline() returns EOF
* on end-of-file or any read failure.
*/
#ifdef CONFIG_NSH_CLE
/* cle() normally returns the number of characters read, but will
* return a negated errno value on end of file or if an error
* occurs. Either will cause the session to terminate.
*/
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
INSTREAM(pstate), OUTSTREAM(pstate));
if (ret < 0)
{
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
"cle", NSH_ERRNO_OF(-ret));
continue;
}
#else
/* Display the prompt string */
fputs(g_nshprompt, pstate->cn_outstream);
fflush(pstate->cn_outstream);
/* 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.
*/
ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
INSTREAM(pstate), OUTSTREAM(pstate));
if (ret == EOF)
{
/* NOTE: readline() does not set the errno variable, but
* perhaps we will be lucky and it will still be valid.
*/
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
"readline", NSH_ERRNO);
ret = EXIT_SUCCESS;
break;
}
#endif
/* Parse process the command */
nsh_parse(vtbl, pstate->cn_line);
fflush(pstate->cn_outstream);
}
}
else if (strcmp(argv[1], "-h") == 0)
{
ret = nsh_output(vtbl, "Usage: %s [<script-path>|-c <command>]\n",
argv[0]);
}
else if (strcmp(argv[1], "-c") != 0)
{
#if defined(CONFIG_NFILE_STREAMS) && !defined(CONFIG_NSH_DISABLESCRIPT)
/* Execute the shell script */
ret = nsh_script(vtbl, argv[0], argv[1]);
#endif
}
else if (argc >= 3)
{
/* Parse process the command */
nsh_parse(vtbl, pstate->cn_line);
ret = nsh_parse(vtbl, argv[2]);
#ifdef CONFIG_NFILE_STREAMS
fflush(pstate->cn_outstream);
#endif
}
/* 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;
return ret;
}

View File

@ -41,6 +41,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef CONFIG_NSH_CLE
# include "system/cle.h"
@ -71,15 +72,13 @@
* Input Parameters:
* pstate - Abstracts the underlying session.
*
* Returned Values:
* EXIT_SUCCESS only
*
****************************************************************************/
int nsh_session(FAR struct console_stdio_s *pstate, bool login)
int nsh_session(FAR struct console_stdio_s *pstate,
bool login, int argc, FAR char *argv[])
{
FAR struct nsh_vtbl_s *vtbl;
int ret;
int ret = EXIT_FAILURE;
DEBUGASSERT(pstate);
vtbl = &pstate->cn_vtbl;
@ -116,63 +115,86 @@ int nsh_session(FAR struct console_stdio_s *pstate, bool login)
#endif
}
/* Then enter the command line parsing loop */
for (; ; )
if (argc < 2)
{
/* For the case of debugging the USB console...
* dump collected USB trace data
*/
/* Then enter the command line parsing loop */
#ifdef CONFIG_NSH_USBDEV_TRACE
nsh_usbtrace();
#endif
/* Get the next line of input. */
#ifdef CONFIG_NSH_CLE
/* cle() normally returns the number of characters read, but will
* return a negated errno value on end of file or if an error occurs.
* Either will cause the session to terminate.
*/
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
stdin, stdout);
if (ret < 0)
for (; ; )
{
printf(g_fmtcmdfailed, "nsh_session", "cle", NSH_ERRNO_OF(-ret));
return EXIT_SUCCESS;
}
#else
/* Display the prompt string */
printf("%s", g_nshprompt);
/* readline () normally returns the number of characters read, but will
* return EOF on end of file or if an error occurs. Either will cause
* the session to terminate.
*/
ret = std_readline(pstate->cn_line, CONFIG_NSH_LINELEN);
if (ret == EOF)
{
/* NOTE: readline() does not set the errno variable, but perhaps we
* will be lucky and it will still be valid.
/* For the case of debugging the USB console...
* dump collected USB trace data
*/
printf(g_fmtcmdfailed, "nsh_session", "readline", NSH_ERRNO);
return EXIT_SUCCESS;
}
#ifdef CONFIG_NSH_USBDEV_TRACE
nsh_usbtrace();
#endif
/* Get the next line of input. */
#ifdef CONFIG_NSH_CLE
/* cle() normally returns the number of characters read, but will
* return a negated errno value on end of file or if an error
* occurs. Either will cause the session to terminate.
*/
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
stdin, stdout);
if (ret < 0)
{
printf(g_fmtcmdfailed,
"nsh_session", "cle", NSH_ERRNO_OF(-ret));
continue;
}
#else
/* Display the prompt string */
printf("%s", g_nshprompt);
/* readline () normally returns the number of characters read, but
* will return EOF on end of file or if an error occurs. Either
* will cause the session to terminate.
*/
ret = std_readline(pstate->cn_line, CONFIG_NSH_LINELEN);
if (ret == EOF)
{
/* NOTE: readline() does not set the errno variable, but
* perhaps we will be lucky and it will still be valid.
*/
printf(g_fmtcmdfailed, "nsh_session", "readline", NSH_ERRNO);
ret = EXIT_SUCCESS;
break;
}
#endif
/* Parse process the command */
nsh_parse(vtbl, pstate->cn_line);
}
}
else if (strcmp(argv[1], "-h") == 0)
{
ret = nsh_output(vtbl, "Usage: %s [<script-path>|-c <command>]\n",
argv[0]);
}
else if (strcmp(argv[1], "-c") != 0)
{
#if defined(CONFIG_NFILE_STREAMS) && !defined(CONFIG_NSH_DISABLESCRIPT)
/* Execute the shell script */
ret = nsh_script(vtbl, argv[0], argv[1]);
#endif
}
else if (argc >= 3)
{
/* Parse process the command */
nsh_parse(vtbl, pstate->cn_line);
ret = nsh_parse(vtbl, argv[2]);
#ifdef CONFIG_NFILE_STREAMS
fflush(pstate->cn_outstream);
#endif
}
/* 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;
return ret;
}

View File

@ -73,40 +73,13 @@
int nsh_system(int argc, FAR char *argv[])
{
FAR struct console_stdio_s *pstate = nsh_newconsole();
FAR struct nsh_vtbl_s *vtbl;
int ret = EXIT_FAILURE;
int ret;
DEBUGASSERT(pstate != NULL);
vtbl = &pstate->cn_vtbl;
if (argc < 2)
{
/* Execute the interactive shell */
/* Execute the session */
ret = nsh_session(pstate, false);
}
else if (strcmp(argv[1], "-h") == 0)
{
ret = nsh_output(vtbl, "Usage: %s [<script-path>|-c <command>]\n",
argv[0]);
}
else if (strcmp(argv[1], "-c") != 0)
{
#if CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
/* Execute the shell script */
ret = nsh_script(vtbl, argv[0], argv[1]);
#endif
}
else if (argc >= 3)
{
/* Parse process the command */
ret = nsh_parse(vtbl, argv[2]);
#if CONFIG_NFILE_STREAMS > 0
fflush(pstate->cn_outstream);
#endif
}
ret = nsh_session(pstate, false, argc, argv);
/* Exit upon return */

View File

@ -99,6 +99,7 @@ static inline int date_month(FAR const char *abbrev)
return i;
}
}
return ERROR;
}
#endif
@ -108,7 +109,8 @@ static inline int date_month(FAR const char *abbrev)
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_DATE
static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name)
static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl,
FAR const char *name)
{
static const char format[] = "%a, %b %d %H:%M:%S %Y";
struct timespec ts;
@ -127,7 +129,7 @@ static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl, FAR const char *nam
/* Break the current time up into the format needed by strftime */
if (gmtime_r((FAR const time_t*)&ts.tv_sec, &tm) == NULL)
if (gmtime_r((FAR const time_t *)&ts.tv_sec, &tm) == NULL)
{
nsh_error(vtbl, g_fmtcmdfailed, name, "gmtime_r", NSH_ERRNO);
return ERROR;
@ -152,8 +154,8 @@ static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl, FAR const char *nam
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_DATE
static inline int date_settime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name,
FAR char *newtime)
static inline int date_settime(FAR struct nsh_vtbl_s *vtbl,
FAR const char *name, FAR char *newtime)
{
struct timespec ts;
struct tm tm;
@ -165,9 +167,10 @@ static inline int date_settime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name
memset(&tm, 0, sizeof(tm));
/* Only this date format is supported: MMM DD HH:MM:SS YYYY */
/* Get the month abbreviation */
token = strtok_r(newtime, " \t",&saveptr);
token = strtok_r(newtime, " \t", &saveptr);
if (token == NULL)
{
goto errout_bad_parm;
@ -179,9 +182,11 @@ static inline int date_settime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name
goto errout_bad_parm;
}
/* Get the day of the month. NOTE: Accepts day-of-month up to 31 for all months */
/* Get the day of the month.
* NOTE: Accepts day-of-month up to 31 for all months
*/
token = strtok_r(NULL, " \t",&saveptr);
token = strtok_r(NULL, " \t", &saveptr);
if (token == NULL)
{
goto errout_bad_parm;
@ -304,8 +309,8 @@ int cmd_time(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
ret = clock_gettime(TIME_CLOCK, &start);
if (ret < 0)
{
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO);
return ERROR;
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO);
return ERROR;
}
/* Save state */
@ -330,7 +335,8 @@ int cmd_time(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
ret = clock_gettime(TIME_CLOCK, &end);
if (ret < 0)
{
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO);
nsh_error(vtbl, g_fmtcmdfailed,
argv[0], "clock_gettime", NSH_ERRNO);
ret = ERROR;
}
else
@ -370,7 +376,6 @@ int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
FAR char *newtime = NULL;
FAR const char *errfmt;
bool badarg = false;
int option;
int ret;
@ -386,18 +391,9 @@ int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
}
else /* option = '?' */
{
/* We need to parse to the end anyway so that getopt stays healthy */
badarg = true;
errfmt = g_fmtarginvalid;
goto errout;
}
}
/* If a bad argument was encountered then exit with an error */
if (badarg)
{
errfmt = g_fmtarginvalid;
goto errout;
}
/* optind < argc-1 means that there are additional, unexpected arguments on

View File

@ -346,7 +346,7 @@ int nsh_consolemain(int argc, FAR char *argv[])
/* Execute the session */
nsh_session(pstate, true);
nsh_session(pstate, true, argc, argv);
/* Switch to /dev/null because we probably no longer have a
* valid console device.

View File

@ -165,7 +165,7 @@ int main(int argc, FAR char *argv[])
#ifdef CONFIG_NSH_CONSOLE
/* If the serial console front end is selected, run it on this thread */
ret = nsh_consolemain(0, NULL);
ret = nsh_consolemain(argc, argv);
/* nsh_consolemain() should not return. So if we get here, something
* is wrong.