Back quoted NSH arguments now functional

This commit is contained in:
Gregory Nutt 2014-01-11 09:50:54 -06:00
parent d499f287ad
commit 65b4921b23
6 changed files with 445 additions and 100 deletions

View File

@ -769,4 +769,6 @@
* apps/nshlib/nsh_parse.c: Add initial support of commands enclosed
in back quotes as command arguments. Functionality still incomplete
on initial commit (2014-1-10).
* Logic to support commands enclosed in back quotes is functional
but not thoroughly tested (2014-1-11).

View File

@ -277,11 +277,11 @@ config NSH_DISABLE_SEMICOLON
command separated by a semicolon. You can disable this feature to
save a little memory on FLASH challenged platforms.
config NSH_FUNCPARMS
bool "Enable function parameters"
config NSH_CMDPARMS
bool "Enable commands as parameters"
default n
---help---
If selected, then the output from cmds, from file applications, and
If selected, then the output from commands, from file applications, and
from NSH built-in commands can be used as arguments to other
commands. The entity to be executed is identified by enclosing the
command line in back quotes. For example,
@ -292,14 +292,15 @@ config NSH_FUNCPARMS
environment variable BAR. The value of the environment variable FOO
is then set output of myprogram on stdout.
This feature is disabled by default.
Because this feature commits significant resourse, it is disabled by
default.
config NSH_TMPDIR
string "Temporary file directory"
default "/tmp"
depends on NSH_FUNCPARMS
depends on NSH_CMDPARMS
---help---
If NSH_FUNCPARMS is selected, then function output will be retained
If NSH_CMDPARMS is selected, then function output will be retained
in a temporary file. In that case, this string must be provided to
specify the full path to a directory where temporary files can be
created. This would be a good application of RAM disk: To provide
@ -312,21 +313,21 @@ config NSH_MAXARGUMENTS
The maximum number of NSH command arguments.
Default: 6
config NSH_ENVCAT
bool "Concatenation of environment variables"
config NSH_ARGCAT
bool "Concatenation of argument strings"
default n
---help---
Support concatenation of strings with environment variables. For
example:
Support concatenation of strings with environment variables or command
output. For example:
set FOO XYZ
set BAR 123
set FOOBAR ABC_${FOO}_${BAR}
would set the environment variable FOO to XYZ, BAR to 123 and FOOBAR
to ABC_XYZ_123. If NSH_ENV, then a slightly small FLASH footprint
results but then also only simple environment variables like $FOO
can be used on the command line.
to ABC_XYZ_123. If NSH_ARGCAT is not selected, then a slightly small
FLASH footprint results but then also only simple environment
variables like $FOO can be used on the command line.
config NSH_NESTDEPTH
int "Maximum command nesting"

View File

@ -65,6 +65,30 @@ Command Overview
Multiple commands per line. NSH will accept multiple commands per
command line with each command separated with the semi-colon character (;).
If CONFIG_NSH_CMDPARMS is selected, then the output from commands, from
file applications, and from NSH built-in commands can be used as arguments
to other commands. The entity to be executed is identified by enclosing
the command line in back quotes. For example,
set FOO `myprogram $BAR`
Will execute the program named myprogram passing it the value of the
environment variable BAR. The value of the environment variable FOO
is then set output of myprogram on stdout. Because this feature commits
significant resources, it is disabled by default.
If CONFIG_NSH_ARGCAT is selected, the support concatenation of strings
with environment variables or command output. For example:
set FOO XYZ
set BAR 123
set FOOBAR ABC_${FOO}_${BAR}
would set the environment variable FOO to XYZ, BAR to 123 and FOOBAR
to ABC_XYZ_123. If NSH_ARGCAT is not selected, then a slightly small
FLASH footprint results but then also only simple environment
variables like $FOO can be used on the command line.
Conditional Command Execution
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -1007,6 +1031,42 @@ NSH-Specific Configuration Settings
feature to save a little memory on FLASH challenged platforms.
Default: n
* CONFIG_NSH_CMDPARMS
If selected, then the output from commands, from file applications, and
from NSH built-in commands can be used as arguments to other
commands. The entity to be executed is identified by enclosing the
command line in back quotes. For example,
set FOO `myprogram $BAR`
Will execute the program named myprogram passing it the value of the
environment variable BAR. The value of the environment variable FOO
is then set output of myprogram on stdout. Because this feature commits
significant resources, it is disabled by default.
* CONFIG_NSH_TMPDIR
If CONFIG_NSH_CMDPARMS is selected, then function output will be retained
in a temporary file. In that case, this string must be provided to
specify the full path to a directory where temporary files can be
created. This would be a good application of RAM disk: To provide
temporary storage for function output.
* CONFIG_NSH_MAXARGUMENTS
The maximum number of NSH command arguments. Default: 6
* CONFIG_NSH_ARGCAT
Support concatenation of strings with environment variables or command
output. For example:
set FOO XYZ
set BAR 123
set FOOBAR ABC_${FOO}_${BAR}
would set the environment variable FOO to XYZ, BAR to 123 and FOOBAR
to ABC_XYZ_123. If NSH_ARGCAT is not selected, then a slightly small
FLASH footprint results but then also only simple environment
variables like $FOO can be used on the command line.
* CONFIG_NSH_NESTDEPTH
The maximum number of nested if-then[-else]-fi sequences that
are permissable. Default: 3

View File

@ -72,14 +72,14 @@
# undef CONFIG_NSH_TELNET
# undef CONFIG_NSH_FILE_APPS
# undef CONFIG_NSH_TELNET
# undef CONFIG_NSH_FUNCPARMS
# undef CONFIG_NSH_CMDPARMS
#endif
/* If CONFIG_NSH_FUNCPARMS is selected, then the path to a directory to
/* If CONFIG_NSH_CMDPARMS is selected, then the path to a directory to
* hold temporary files must be provided.
*/
#if defined(CONFIG_NSH_FUNCPARMS) && !defined(CONFIG_NSH_TMPDIR)
#if defined(CONFIG_NSH_CMDPARMS) && !defined(CONFIG_NSH_TMPDIR)
# define CONFIG_NSH_TMPDIR "/tmp"
#endif

View File

@ -173,7 +173,6 @@ static void dd_outfcloseblk(struct dd_s *dd)
}
#endif
/****************************************************************************
* Name: dd_outfclosech
****************************************************************************/
@ -325,7 +324,7 @@ static int dd_readch(struct dd_s *dd)
}
/****************************************************************************
* Name: dd_infopen
* Name: dd_filetype
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOINT
@ -391,6 +390,7 @@ static inline int dd_infopen(const char *name, struct dd_s *dd)
dd->infread = dd_readblk;
dd->infclose = dd_infcloseblk;
}
return OK;
}
#else
@ -403,6 +403,7 @@ static inline int dd_infopen(const char *name, struct dd_s *dd)
nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
return ERROR;
}
return OK;
}
#endif
@ -450,6 +451,7 @@ static inline int dd_outfopen(const char *name, struct dd_s *dd)
dd->outfwrite = dd_writech; /* Character oriented write */
dd->outfclose = dd_outfclosech;
}
return OK;
}
#else
@ -461,6 +463,7 @@ static inline int dd_outfopen(const char *name, struct dd_s *dd)
nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
return ERROR;
}
return OK;
}
#endif
@ -614,22 +617,27 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
dd.sector++;
}
}
ret = OK;
errout_with_outf:
DD_INCLOSE(&dd);
errout_with_inf:
DD_OUTCLOSE(&dd);
free(dd.buffer);
errout_with_paths:
if (infile)
{
free(infile);
}
if (outfile)
{
free(outfile);
}
return ret;
}

View File

@ -45,6 +45,10 @@
#include <errno.h>
#include <debug.h>
#ifdef CONFIG_NSH_CMDPARMS
# include <sys/stat.h>
#endif
#include <apps/nsh.h>
#include "nsh.h"
@ -53,6 +57,37 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* If CONFIG_NSH_CMDPARMS or CONFIG_NSH_ARGCAT is enabled, then we will need
* retain a list of memory allocations to be freed at the completion of
* command processing.
*/
#undef HAVE_MEMLIST
#if defined(CONFIG_NSH_CMDPARMS) || defined(CONFIG_NSH_ARGCAT)
# define HAVE_MEMLIST 1
#endif
#if defined(HAVE_MEMLIST) && !defined(CONFIG_NSH_MAXALLOCS)
# ifdef CONFIG_NSH_ARGCAT
# define CONFIG_NSH_MAXALLOCS (2*CONFIG_NSH_MAXARGUMENTS)
# else
# define CONFIG_NSH_MAXALLOCS CONFIG_NSH_MAXARGUMENTS
# endif
#endif
/* Allocation list helper macros */
#ifdef HAVE_MEMLIST
# define NSH_MEMLIST_TYPE struct nsh_memlist_s
# define NSH_MEMLIST_INIT(m) memset(&(m), 0, sizeof(struct nsh_memlist_s));
# define NSH_MEMLIST_ADD(m,a) nsh_memlist_add(m,a)
# define NSH_MEMLIST_FREE(m) nsh_memlist_free(m)
#else
# define NSH_MEMLIST_TYPE uint8_t
# define NSH_MEMLIST_INIT(m) do { (m) = 0; } while (0)
# define NSH_MEMLIST_ADD(m,a)
# define NSH_MEMLIST_FREE(m,a)
#endif
/****************************************************************************
* Private Types
@ -70,10 +105,26 @@ struct cmdarg_s
};
#endif
/* This structure describes the allocation list */
#ifdef HAVE_MEMLIST
struct nsh_memlist_s
{
int nallocs; /* Number of allocations */
FAR char *allocations[CONFIG_NSH_MAXALLOCS];
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifdef HAVE_MEMLIST
static void nsh_memlist_add(FAR struct nsh_memlist_s *memlist,
FAR char *address);
static void nsh_memlist_free(FAR struct nsh_memlist_s *memlist);
#endif
#ifndef CONFIG_NSH_DISABLEBG
static void nsh_releaseargs(struct cmdarg_s *arg);
static pthread_addr_t nsh_child(pthread_addr_t arg);
@ -85,20 +136,31 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result);
static int nsh_execute(FAR struct nsh_vtbl_s *vtbl,
int argc, FAR char *argv[], FAR const char *redirfile,
int oflags);
static char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr);
#ifdef CONFIG_NSH_CMDPARMS
static FAR char *nsh_filecat(FAR struct nsh_vtbl_s *vtbl, FAR char *s1,
FAR const char *filename);
static FAR char *nsh_cmdparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
FAR char **allocation);
#endif
#ifdef CONFIG_NSH_ARGCAT
static int nsh_strcat(FAR char *s1, FAR const char *s2);
#endif
static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr,
FAR NSH_MEMLIST_TYPE *memlist);
#ifndef CONFIG_NSH_DISABLESCRIPT
static bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl);
static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl,
FAR char **ppcmd, FAR char **saveptr);
static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
FAR char **saveptr, FAR NSH_MEMLIST_TYPE *memlist);
#endif
#ifndef CONFIG_NSH_DISABLEBG
static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
FAR char **saveptr);
FAR char **saveptr, FAR NSH_MEMLIST_TYPE *memlist);
#endif
#ifdef CONFIG_NSH_FUNCPARMS
#ifdef CONFIG_NSH_CMDPARMS
static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
FAR const char *redirfile);
#endif
@ -172,6 +234,48 @@ const char g_fmtsignalrecvd[] = "nsh: %s: Interrupted by signal\n";
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nsh_memlist_add
****************************************************************************/
#ifdef HAVE_MEMLIST
static void nsh_memlist_add(FAR struct nsh_memlist_s *memlist,
FAR char *address)
{
if (memlist)
{
int index = memlist->nallocs;
if (index < CONFIG_NSH_MAXALLOCS)
{
memlist->allocations[index] = address;
memlist->nallocs = index + 1;
}
}
}
#endif
/****************************************************************************
* Name: nsh_memlist_free
****************************************************************************/
#ifdef HAVE_MEMLIST
static void nsh_memlist_free(FAR struct nsh_memlist_s *memlist)
{
if (memlist)
{
int index;
for (index = 0; index < memlist->nallocs; index++)
{
free(memlist->allocations[index]);
memlist->allocations[index] = NULL;
}
memlist->nallocs = 0;
}
}
#endif
/****************************************************************************
* Name: nsh_releaseargs
****************************************************************************/
@ -204,6 +308,7 @@ static void nsh_releaseargs(struct cmdarg_s *arg)
{
free(arg->argv[i]);
}
free(arg);
}
#endif
@ -558,15 +663,202 @@ errout:
return nsh_saveresult(vtbl, true);
}
/****************************************************************************
* Name: nsh_filecat
****************************************************************************/
#ifdef CONFIG_NSH_CMDPARMS
static FAR char *nsh_filecat(FAR struct nsh_vtbl_s *vtbl, FAR char *s1,
FAR const char *filename)
{
struct stat buf;
size_t s1size = 0;
size_t allocsize;
ssize_t nbytesread;
FAR char *argument;
int index;
int fd;
int ret;
/* Get the size of the string */
if (s1)
{
s1size = (size_t)strlen(s1);
}
/* Get the size of file */
ret = stat(filename, &buf);
if (ret != 0)
{
nsh_output(vtbl, g_fmtcmdfailed, "``", "stat", NSH_ERRNO);
return NULL;
}
/* Get the total allocation size */
allocsize = s1size + (size_t)buf.st_size + 1;
argument = (FAR char *)realloc(s1, allocsize);
if (!argument)
{
nsh_output(vtbl, g_fmtcmdoutofmemory, "``");
return NULL;
}
/* Open the source file for reading */
fd = open(filename, O_RDONLY);
if (fd < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, "``", "open", NSH_ERRNO);
goto errout_with_alloc;
}
/* Now copy the file. Loop until the entire file has been transferred to
* the allocated string (after the original contents of s1size bytes.
*/
for (index = s1size; index < allocsize - 1; )
{
/* Loop until we successfully read something , we encounter the
* end-of-file, or until a read error occurs
*/
do
{
nbytesread = read(fd, &argument[index], IOBUFFERSIZE);
if (nbytesread == 0)
{
/* Unexpected end of file -- Break out of the loop */
break;
}
else if (nbytesread < 0)
{
/* EINTR is not an error (but will still stop the copy) */
#ifndef CONFIG_DISABLE_SIGNALS
if (errno == EINTR)
{
nsh_output(vtbl, g_fmtsignalrecvd, "``");
}
else
#endif
{
/* Read error */
nsh_output(vtbl, g_fmtcmdfailed, "``", "read", NSH_ERRNO);
}
goto errout_with_fd;
}
}
while (nbytesread <= 0);
/* Update the index based upon the number of bytes read */
index += nbytesread;
}
/* Make sure that the new string is null terminated */
argument[index] = '\0';
return argument;
errout_with_fd:
close(fd);
errout_with_alloc:
free(argument);
return NULL;
}
#endif
/****************************************************************************
* Name: nsh_cmdparm
****************************************************************************/
#ifdef CONFIG_NSH_CMDPARMS
static FAR char *nsh_cmdparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
FAR char **allocation)
{
FAR char *tmpfile;
FAR char *argument;
int ret;
/* We cannot process the command argument if there is no allocation pointer */
if (!allocation)
{
return NULL;
}
/* Create a unique file name using the task ID */
tmpfile = NULL;
ret = asprintf(&tmpfile, "%s/TMP%d.dat", CONFIG_NSH_TMPDIR, getpid());
if (ret < 0 || !tmpfile)
{
nsh_output(vtbl, g_fmtcmdoutofmemory, "``");
return NULL;
}
/* Execute the command that will re-direct the output of the command to
* the temporary file. This is a simple command that can't handle most
* options.
*/
ret = nsh_parse_funcparm(vtbl, cmdline, tmpfile);
if (ret != OK)
{
/* Report the failure */
nsh_output(vtbl, g_fmtcmdfailed, "``", "exec", NSH_ERRNO);
free(tmpfile);
return NULL;
}
/* Concatenate the file contents with the current allocation */
argument = nsh_filecat(vtbl, *allocation, tmpfile);
*allocation = argument;
/* We can now unlink the tmpfile and free the tmpfile string */
ret = unlink(tmpfile);
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, "``", "unlink", NSH_ERRNO);
}
free(tmpfile);
return argument;
}
#endif
/****************************************************************************
* Name: nsh_strcat
****************************************************************************/
#ifdef CONFIG_NSH_ARGCAT
static int nsh_strcat(FAR char *s1, FAR const char *s2)
{
}
#endif
/****************************************************************************
* Name: nsh_argument
****************************************************************************/
static char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr)
static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr,
FAR NSH_MEMLIST_TYPE *memlist)
{
FAR char *pbegin = *saveptr;
FAR char *pend = NULL;
const char *term;
FAR char *pbegin = *saveptr;
FAR char *pend = NULL;
FAR char *allocation = NULL;
FAR char *argument = NULL;
FAR const char *term;
#ifndef CONFIG_DISABLE_ENVIRON
bool quoted = false;
#endif
@ -614,17 +906,14 @@ static char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr)
pbegin = NULL;
}
#ifdef CONFIG_NSH_FUNCPARMS
#ifdef CONFIG_NSH_CMDPARMS
/* Are we being asked to use the output from another command or program
* as an input parameters for this command?
*/
else if (*pbegin == '`')
{
FAR char *tmpfile;
int ret;
/* Yes, find the terminated backquote */
/* Yes, find the terminating backquote */
for (++pbegin, pend = pbegin; *pend && *pend != '`'; pend++);
@ -645,51 +934,9 @@ static char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr)
*pend++ = '\0';
*saveptr = pend;
/* Create a unique file name using the task ID */
/* Then execute the command to get the paramter value */
tmpfile = NULL;
ret = asprintf(&tmpfile, "%s/TMP%d.dat", CONFIG_NSH_TMPDIR, getpid());
if (ret < 0 || !tmpfile)
{
nsh_output(vtbl, g_fmtcmdoutofmemory, "``");
return NULL;
}
/* Execute the command that will re-direct the output of the command
* to the temporary file. This is a simple command that can't handle
* most options.
*/
ret = nsh_parse_funcparm(vtbl, pbegin, tmpfile);
if (ret != OK)
{
/* Report the failure */
#warning Logic Missing
free(tmpfile);
return NULL;
}
/* mmap() the file contain the output from the command so that
* we can refer to it like any string.
*/
#warning Logic Missing
/* setup so that we can unmap the memory region and close the
* file after the command completes.
*/
#warning Logic Missing
/* We can not unlink the tmpfile and free the tmpfile string */
ret = unlink(tmpfile);
if (ret < 0)
{
nsh_output(vtbl, g_fmtcmdfailed, "``", "unlink", NSH_ERRNO);
}
free(tmpfile);
return "OH NO!";
argument = nsh_cmdparm(vtbl, pbegin, &allocation);
}
#endif
@ -780,11 +1027,27 @@ static char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr)
}
}
#endif
/* The argument to be returned is simply the beginning of the
* delimited string.
*/
argument = pbegin;
}
/* Return the beginning of the token. */
return pbegin;
/* If any memory was allocated for this argument, make sure that it is
* added to the list of memory to be freed at the end of commend
* processing.
*/
if (allocation)
{
NSH_MEMLIST_ADD(memlist, allocation);
}
/* Return the parsed argument. */
return argument;
}
/****************************************************************************
@ -825,7 +1088,7 @@ static bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
#ifndef CONFIG_NSH_DISABLESCRIPT
static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
FAR char **saveptr)
FAR char **saveptr, FAR NSH_MEMLIST_TYPE *memlist)
{
struct nsh_parser_s *np = &vtbl->np;
FAR char *cmd = *ppcmd;
@ -839,7 +1102,7 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
{
/* Get the cmd following the if */
*ppcmd = nsh_argument(vtbl, saveptr);
*ppcmd = nsh_argument(vtbl, saveptr, memlist);
if (!*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "if");
@ -876,7 +1139,7 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
{
/* Get the cmd following the then -- there shouldn't be one */
*ppcmd = nsh_argument(vtbl, saveptr);
*ppcmd = nsh_argument(vtbl, saveptr, memlist);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "then");
@ -896,7 +1159,7 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
{
/* Get the cmd following the else -- there shouldn't be one */
*ppcmd = nsh_argument(vtbl, saveptr);
*ppcmd = nsh_argument(vtbl, saveptr, memlist);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "else");
@ -916,7 +1179,7 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
{
/* Get the cmd following the fi -- there should be one */
*ppcmd = nsh_argument(vtbl, saveptr);
*ppcmd = nsh_argument(vtbl, saveptr, memlist);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "fi");
@ -965,7 +1228,7 @@ errout:
#ifndef CONFIG_NSH_DISABLEBG
static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
FAR char **saveptr)
FAR char **saveptr, FAR NSH_MEMLIST_TYPE *memlist)
{
FAR char *cmd = *ppcmd;
@ -984,10 +1247,10 @@ static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* Get the cmd (or -d option of nice command) */
cmd = nsh_argument(vtbl, saveptr);
cmd = nsh_argument(vtbl, saveptr, memlist);
if (cmd && strcmp(cmd, "-d") == 0)
{
FAR char *val = nsh_argument(vtbl, saveptr);
FAR char *val = nsh_argument(vtbl, saveptr, memlist);
if (val)
{
char *endptr;
@ -998,7 +1261,7 @@ static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
nsh_output(vtbl, g_fmtarginvalid, "nice");
return ERROR;
}
cmd = nsh_argument(vtbl, saveptr);
cmd = nsh_argument(vtbl, saveptr, memlist);
}
}
@ -1017,7 +1280,7 @@ static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
*
* Description:
* This function parses and executes a simple NSH command. Output is
* always redirected. Function function supports function paramers like
* always redirected. This function supports command parameters like
*
* set FOO `hello`
*
@ -1026,10 +1289,11 @@ static int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
*
****************************************************************************/
#ifdef CONFIG_NSH_FUNCPARMS
#ifdef CONFIG_NSH_CMDPARMS
static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
FAR const char *redirfile)
{
NSH_MEMLIST_TYPE memlist;
FAR char *argv[MAX_ARGV_ENTRIES];
FAR char *saveptr;
FAR char *cmd;
@ -1041,6 +1305,7 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
/* Initialize parser state */
memset(argv, 0, MAX_ARGV_ENTRIES*sizeof(FAR char *));
NSH_MEMLIST_INIT(memlist);
/* If any options like nice, redirection, or backgrounding are attempted,
* these will not be recognized and will just be passed through as
@ -1048,7 +1313,7 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
*/
#ifndef CONFIG_NSH_DISABLEBG
/* The function is never backgrounded . Remember the current backgrouding
/* The command is never backgrounded . Remember the current backgrounding
* state
*/
@ -1064,7 +1329,7 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
/* Parse out the command at the beginning of the line */
saveptr = cmdline;
cmd = nsh_argument(vtbl, &saveptr);
cmd = nsh_argument(vtbl, &saveptr, &memlist);
/* Check if any command was provided -OR- if command processing is
* currently disabled.
@ -1077,10 +1342,11 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
#endif
{
/* An empty line is not an error and an unprocessed command cannot
* generate an error, but neither should they change the last
* command status.
* generate an error, but neither should it change the last command
* status.
*/
NSH_MEMLIST_FREE(&memlist);
return OK;
}
@ -1097,7 +1363,7 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
argv[0] = cmd;
for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++)
{
argv[argc] = nsh_argument(vtbl, &saveptr);
argv[argc] = nsh_argument(vtbl, &saveptr, &memlist);
if (!argv[argc])
{
break;
@ -1123,6 +1389,8 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
vtbl->np.np_bg = bgsave;
#endif
vtbl->np.np_redirect = redirsave;
NSH_MEMLIST_FREE(&memlist);
return ret;
}
#endif
@ -1137,6 +1405,7 @@ static int nsh_parse_funcparm(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline,
static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
{
NSH_MEMLIST_TYPE memlist;
FAR char *argv[MAX_ARGV_ENTRIES];
FAR char *saveptr;
FAR char *cmd;
@ -1150,6 +1419,7 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
/* Initialize parser state */
memset(argv, 0, MAX_ARGV_ENTRIES*sizeof(FAR char *));
NSH_MEMLIST_INIT(memlist);
#ifndef CONFIG_NSH_DISABLEBG
vtbl->np.np_bg = false;
@ -1162,13 +1432,14 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
/* Parse out the command at the beginning of the line */
saveptr = cmdline;
cmd = nsh_argument(vtbl, &saveptr);
cmd = nsh_argument(vtbl, &saveptr, &memlist);
/* Handler if-then-else-fi */
#ifndef CONFIG_NSH_DISABLESCRIPT
if (nsh_ifthenelse(vtbl, &cmd, &saveptr) != 0)
if (nsh_ifthenelse(vtbl, &cmd, &saveptr, &memlist) != 0)
{
NSH_MEMLIST_FREE(&memlist);
return nsh_saveresult(vtbl, true);
}
#endif
@ -1176,8 +1447,9 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
/* Handle nice */
#ifndef CONFIG_NSH_DISABLEBG
if (nsh_nice(vtbl, &cmd, &saveptr) != 0)
if (nsh_nice(vtbl, &cmd, &saveptr, &memlist) != 0)
{
NSH_MEMLIST_FREE(&memlist);
return nsh_saveresult(vtbl, true);
}
#endif
@ -1193,10 +1465,11 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
#endif
{
/* An empty line is not an error and an unprocessed command cannot
* generate an error, but neither should they change the last
* command status.
* generate an error, but neither should it change the last command
* status.
*/
NSH_MEMLIST_FREE(&memlist);
return OK;
}
@ -1216,7 +1489,7 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
argv[0] = cmd;
for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++)
{
argv[argc] = nsh_argument(vtbl, &saveptr);
argv[argc] = nsh_argument(vtbl, &saveptr, &memlist);
if (!argv[argc])
{
break;
@ -1285,6 +1558,7 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline)
}
#endif
NSH_MEMLIST_FREE(&memlist);
return ret;
}