Newer
Older
/****************************************************************************
* 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
* 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 NuttX 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.
*
****************************************************************************/
/****************************************************************************
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
/****************************************************************************
****************************************************************************/
/* Argument list size
*
* argv[0]: The command name.
* argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
* argv[argc-3]: Possibly '>' or '>>'
* argv[argc-2]: Possibly <file>
* argv[argc-1]: Possibly '&' (if pthreads are enabled)
* argv[argc]: NULL terminating pointer
*
* Maximum size is NSH_MAX_ARGUMENTS+5
*/
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+5)
#else
# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+4)
#endif
#if CONFIG_RR_INTERVAL > 0
# define SCHED_NSH SCHED_RR
#else
# define SCHED_NSH SCHED_FIFO
#endif
/****************************************************************************
****************************************************************************/
const char *cmd; /* Name of the command */
cmd_t handler; /* Function that handles the command */
ubyte minargs; /* Minimum number of arguments (including command) */
ubyte maxargs; /* Maximum number of arguments (including command) */
const char *usage; /* Usage instructions for 'help' command */
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
struct cmdarg_s
{
FAR struct nsh_vtbl_s *vtbl; /* For front-end interaction */
int fd; /* FD for output redirection */
int argc; /* Number of arguments in argv */
FAR char *argv[MAX_ARGV_ENTRIES]; /* Argument list */
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_HELP
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_EXIT
static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif
static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
/****************************************************************************
****************************************************************************/
static const char g_delim[] = " \t\n";
static const char g_redirect1[] = ">";
static const char g_redirect2[] = ">>";
static const char g_exitstatus[] = "$?";
static const char g_success[] = "0";
static const char g_failure[] = "1";
static const struct cmdmap_s g_cmdmap[] =
{
#if !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT) && !defined(CONFIG_EXAMPLES_NSH_DISABLE_TEST)
{ "[", cmd_lbracket, 4, NSH_MAX_ARGUMENTS, "<expression> ]" },
#endif
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_CAT
{ "cat", cmd_cat, 2, NSH_MAX_ARGUMENTS, "<path> [<path> [<path> ...]]" },
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_CD
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_CP
{ "cp", cmd_cp, 3, 3, "<source-path> <dest-path>" },
#if CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_LS
{ "dd", cmd_dd, 3, 6, "if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] [skip=<sectors>]" },
# endif
#endif
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_ECHO
# ifndef CONFIG_DISABLE_ENVIRON
{ "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[<string|$name> [<string|$name>...]]" },
{ "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[<string> [<string>...]]" },
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_EXEC
#endif
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_EXIT
#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_GET
{ "get", cmd_get, 4, 7, "[-b|-n] [-f <local-path>] -h <ip-address> <remote-path>" },
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_HELP
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_IFCONFIG
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_LOSETUP
{ "losetup", cmd_losetup, 3, 6, "[-d <dev-path>] | [[-o <offset>] [-r] <dev-path> <file-path>]" },
# endif
#endif
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_LS
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_MB
{ "mb", cmd_mb, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
#endif
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_MEM
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_MKDIR
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_MKFATFS
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_MKFIFO
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_MKRD
{ "mkrd", cmd_mkrd, 2, 6, "[-m <minor>] [-s <sector-size>] <nsectors>" },
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_MH
{ "mh", cmd_mh, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_MOUNT
{ "mount", cmd_mount, 4, 5, "-t <fstype> <block-device> <dir-path>" },
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_MW
{ "mw", cmd_mw, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_PING
{ "ping", cmd_ping, 2, 6, "[-c <count>] [-i <interval>] <ip-address>" },
# endif
#endif
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_PS
{ "ps", cmd_ps, 1, 1, NULL },
#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_PUT
{ "put", cmd_put, 4, 7, "[-b|-n] [-f <remote-path>] -h <ip-address> <local-path>" },
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_PWD
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_RM
# endif
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_RMDIR
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_SET
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_SH
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_SLEEP
# endif
#endif
#if !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT) && !defined(CONFIG_EXAMPLES_NSH_DISABLE_TEST)
{ "test", cmd_test, 3, NSH_MAX_ARGUMENTS, "<expression>" },
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_UMOUNT
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_UNSET
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_USLEEP
#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_EXAMPLES_NSH_DISABLE_GET
{ "wget", cmd_wget, 2, 4, "[-o <local-path>] <url>" },
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_XD
/****************************************************************************
****************************************************************************/
const char g_nshgreeting[] = "\nNuttShell (NSH)\n";
const char g_nshsyntax[] = "nsh: %s: syntax error\n";
const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n";
const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n";
const char g_fmtargrange[] = "nsh: %s: value out of range\n";
const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n";
const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n";
const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n";
const char g_fmtdeepnesting[] = "nsh: %s: nesting too deep\n";
const char g_fmtcontext[] = "nsh: %s: not valid in this context\n";
#else
const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %d\n";
#endif
const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n";
const char g_fmtinternalerror[] = "nsh: %s: Internal error\n";
/****************************************************************************
****************************************************************************/
/****************************************************************************
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_HELP
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
const struct cmdmap_s *ptr;
nsh_output(vtbl, "NSH command forms:\n");
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
nsh_output(vtbl, " [nice [-d <niceness>>]] <cmd> [> <file>|>> <file>] [&]\n");
#else
nsh_output(vtbl, " <cmd> [> <file>|>> <file>]\n");
#endif
nsh_output(vtbl, "OR\n");
nsh_output(vtbl, " if <cmd>\n");
nsh_output(vtbl, " then\n");
nsh_output(vtbl, " [sequence of <cmd>]\n");
nsh_output(vtbl, " else\n");
nsh_output(vtbl, " [sequence of <cmd>]\n");
nsh_output(vtbl, " fi\n");
for (ptr = g_cmdmap; ptr->cmd; ptr++)
{
if (ptr->usage)
{
/****************************************************************************
****************************************************************************/
static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/****************************************************************************
* Name: cmd_exit
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLE_EXIT
static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
/****************************************************************************
* Name: nsh_execute
****************************************************************************/
static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[])
{
const struct cmdmap_s *cmdmap;
const char *cmd;
cmd_t handler = cmd_unrecognized;
* argv[0]: The command name. This is argv[0] when the arguments
* argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
/* See if the command is one that we understand */
for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++)
{
if (strcmp(cmdmap->cmd, cmd) == 0)
{
/* Check if a valid number of arguments was provided. We
* do this simple, imperfect checking here so that it does
* not have to be performed in each command.
*/
if (argc < cmdmap->minargs)
{
/* Fewer than the minimum number were provided */
return ERROR;
}
else if (argc > cmdmap->maxargs)
{
/* More than the maximum number were provided */
return ERROR;
}
else
{
/* A valid number of arguments were provided (this does
* not mean they are right).
*/
handler = cmdmap->handler;
break;
}
}
}
/****************************************************************************
* Name: nsh_releaseargs
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
static void nsh_releaseargs(struct cmdarg_s *arg)
{
FAR struct nsh_vtbl_s *vtbl = arg->vtbl;
int i;
/* If the output was redirected, then file descriptor should
* be closed. The created task has its one, independent copy of
* the file descriptor
*/
if (vtbl->np.np_redirect)
{
(void)close(arg->fd);
}
/* Released the cloned vtbl instance */
nsh_release(vtbl);
/* Release the cloned args */
for (i = 0; i < arg->argc; i++)
{
free(arg->argv[i]);
}
free(arg);
}
#endif
/****************************************************************************
* Name: nsh_child
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
static pthread_addr_t nsh_child(pthread_addr_t arg)
{
struct cmdarg_s *carg = (struct cmdarg_s *)arg;
int ret;
dbg("BG %s\n", carg->argv[0]);
/* Execute the specified command on the child thread */
ret = nsh_execute(carg->vtbl, carg->argc, carg->argv);
/* Released the cloned arguments */
dbg("BG %s complete\n", carg->argv[0]);
nsh_releaseargs(carg);
return (void*)ret;
}
#endif
/****************************************************************************
* Name: nsh_cloneargs
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
static inline struct cmdarg_s *nsh_cloneargs(FAR struct nsh_vtbl_s *vtbl,
int fd, int argc, char *argv[])
{
struct cmdarg_s *ret = (struct cmdarg_s *)zalloc(sizeof(struct cmdarg_s));
int i;
if (ret)
{
ret->vtbl = vtbl;
ret->fd = fd;
ret->argc = argc;
for (i = 0; i < argc; i++)
{
ret->argv[i] = strdup(argv[i]);
}
}
return ret;
}
/****************************************************************************
****************************************************************************/
char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr)
char *pbegin = *saveptr;
char *pend = NULL;
const char *term;
#ifndef CONFIG_DISABLE_ENVIRON
boolean quoted = FALSE;
#endif
/* 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 '>' -- redirection of output? */
if (*pbegin == '>')
{
/* Yes.. does it begin with ">>"? */
if (*(pbegin + 1) == '>')
{
*saveptr = pbegin + 2;
/* Does the token begin with '#' -- comment */
else if (*pbegin == '#')
{
/* Return NULL meaning that we are at the end of the line */
*saveptr = pbegin;
pbegin = NULL;
}
/* Otherwise, we are going to have to parse to find the end of
* the token. Does the token begin with '"'?
*/
if (*pbegin == '"')
{
/* Yes.. then only another '"' can terminate the string */
pbegin++;
term = "\"";
#ifndef CONFIG_DISABLE_ENVIRON
quoted = TRUE;
#endif
}
else
{
/* No, then any of the usual terminators will terminate the argument */
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 */
*saveptr = pend;
#ifndef CONFIG_DISABLE_ENVIRON
/* Check for references to environment variables */
/* Check for built-in variables */
if (strcmp(pbegin, g_exitstatus) == 0)
if (vtbl->np.np_fail)
{
return (char*)g_failure;
}
else
{
return (char*)g_success;
}
/* Not a built-in? Return the value of the environment variable with this name */
char *value = getenv(pbegin+1);
if (value)
{
return value;
}
else
{
return (char*)"";
}
/****************************************************************************
* Name: nsh_cmdenabled
****************************************************************************/
static inline boolean nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
{
struct nsh_parser_s *np = &vtbl->np;
boolean ret = !np->np_st[np->np_ndx].ns_disabled;
if (ret)
{
switch (np->np_st[np->np_ndx].ns_state)
{
case NSH_PARSER_NORMAL :
case NSH_PARSER_IF:
default:
break;
case NSH_PARSER_THEN:
ret = !np->np_st[np->np_ndx].ns_ifcond;
break;
case NSH_PARSER_ELSE:
ret = np->np_st[np->np_ndx].ns_ifcond;
break;
}
}
return ret;
}
/****************************************************************************
* Name: nsh_ifthenelse
****************************************************************************/
static inline int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr)
{
if (cmd)
{
/* Check if the command is preceeded by "if" */
if (strcmp(cmd, "if") == 0)
{
/* Get the cmd following the if */
*ppcmd = nsh_argument(vtbl, saveptr);
if (!*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "if");
}
/* Verify that "if" is valid in this context */
if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_NORMAL &&
np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
{
nsh_output(vtbl, g_fmtcontext, "if");
/* Check if we have exceeded the maximum depth of nesting */
if (np->np_ndx >= CONFIG_EXAMPLES_NSH_NESTDEPTH-1)
{
nsh_output(vtbl, g_fmtdeepnesting, "if");
}
/* "Push" the old state and set the new state */
disabled = !nsh_cmdenabled(vtbl);
np->np_ndx++;
np->np_st[np->np_ndx].ns_state = NSH_PARSER_IF;
np->np_st[np->np_ndx].ns_disabled = disabled;
np->np_st[np->np_ndx].ns_ifcond = FALSE;
}
else if (strcmp(cmd, "then") == 0)
{
/* Get the cmd following the then -- there shouldn't be one */
*ppcmd = nsh_argument(vtbl, saveptr);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "then");
}
/* Verify that "then" is valid in this context */
if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_IF)
{
nsh_output(vtbl, g_fmtcontext, "then");
np->np_st[np->np_ndx].ns_state = NSH_PARSER_THEN;
}
else if (strcmp(cmd, "else") == 0)
{
/* Get the cmd following the else -- there shouldn't be one */
*ppcmd = nsh_argument(vtbl, saveptr);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "else");
}
/* Verify that "then" is valid in this context */
if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN)
{
nsh_output(vtbl, g_fmtcontext, "else");
np->np_st[np->np_ndx].ns_state = NSH_PARSER_ELSE;
}
else if (strcmp(cmd, "fi") == 0)
{
/* Get the cmd following the fi -- there should be one */
*ppcmd = nsh_argument(vtbl, saveptr);
if (*ppcmd)
{
nsh_output(vtbl, g_fmtarginvalid, "fi");
}
/* Verify that "fi" is valid in this context */
if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
{
nsh_output(vtbl, g_fmtcontext, "fi");
if (np->np_ndx < 1) /* Shouldn't happen */
{
nsh_output(vtbl, g_fmtinternalerror, "if");
}
/* "Pop" the previous state */
np->np_ndx--;
else if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
{
nsh_output(vtbl, g_fmtcontext, cmd);
np->np_ndx = 0;
np->np_st[0].ns_state = NSH_PARSER_NORMAL;
np->np_st[0].ns_disabled = FALSE;
np->np_st[0].ns_ifcond = FALSE;
/****************************************************************************
* Name: nsh_saveresult
****************************************************************************/
static inline int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, boolean result)
if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
np->np_fail = FALSE;
np->np_st[np->np_ndx].ns_ifcond = result;
}
}
/****************************************************************************
* Name: nsh_nice
****************************************************************************/
#ifndef CONFIG_EXAMPLES_NSH_DISABLEBG
static inline int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr)
{
FAR char *cmd = *ppcmd;
vtbl->np.np_nice = 0;
if (cmd)
{
/* Check if the command is preceded by "nice" */
if (strcmp(cmd, "nice") == 0)
{
/* Nicenesses range from -20 (most favorable scheduling) to 19
* (least favorable). Default is 10.
*/
vtbl->np.np_nice = 10;
/* Get the cmd (or -d option of nice command) */
cmd = nsh_argument(vtbl, saveptr);
if (cmd && strcmp(cmd, "-d") == 0)
{
FAR char *val = nsh_argument(vtbl, saveptr);
if (val)
{
char *endptr;
vtbl->np.np_nice = (int)strtol(val, &endptr, 0);
if (vtbl->np.np_nice > 19 || vtbl->np.np_nice < -20 ||
endptr == val || *endptr != '\0')
{
nsh_output(vtbl, g_fmtarginvalid, "nice");
return ERROR;
}
cmd = nsh_argument(vtbl, saveptr);
}
}
/* Return the real command name */
*ppcmd = cmd;
}
}
return OK;
}
/****************************************************************************
****************************************************************************/
/****************************************************************************
****************************************************************************/
void user_initialize(void)
{
/* stub */
}
/****************************************************************************
****************************************************************************/
int user_start(int argc, char *argv[])
#if defined(CONFIG_EXAMPLES_NSH_CONSOLE) && defined(CONFIG_EXAMPLES_NSH_TELNET)
/* Mount the /etc filesystem */
(void)nsh_romfsetc();
/* Perform architecture-specific initialization (if available) */
(void)nsh_archinitialize();
/* 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_NSH) + sched_get_priority_min(SCHED_NSH)) >> 1;
{
struct sched_param param;
param.sched_priority = mid_priority;
(void)sched_setscheduler(0, SCHED_NSH, ¶m);