From d03aa9112e3a05b2fa0bb1d1079ba7c1e0f6b3f3 Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Wed, 5 Apr 2017 18:25:59 -0600 Subject: [PATCH] Added support for set [{+|-}{e|x|xe|ex}] [ ] Set the 'exit on error control' and/or 'print a trace' of commands when parsing scripts in NSH. The settinngs are in effect from the point of exection, until they are changed again, or in the case of the init script, the settings are returned to the default settings when it exits. Included child scripts will run with the parents settings and changes made in the child script will effect the parent on return. Use 'set -e' to enable and 'set +e' to disable (ignore) the exit condition on commands. The default is -e. Errors cause script to exit. Use 'set -x' to enable and 'set +x' to disable (silence) printing a trace of the script commands as they are ececuted. The default is +x. No printing of a trace of script commands as they are executed. --- nshlib/README.txt | 38 +++++++++++++++++-- nshlib/nsh.h | 34 +++++++++++++++-- nshlib/nsh_command.c | 10 +++-- nshlib/nsh_console.c | 6 +++ nshlib/nsh_consolemain.c | 6 +++ nshlib/nsh_envcmds.c | 81 ++++++++++++++++++++++++++++++++++------ nshlib/nsh_script.c | 7 +++- 7 files changed, 160 insertions(+), 22 deletions(-) diff --git a/nshlib/README.txt b/nshlib/README.txt index 05ba319e9..8edf053b7 100644 --- a/nshlib/README.txt +++ b/nshlib/README.txt @@ -1017,10 +1017,10 @@ o rmmod NAME INIT UNINIT ARG TEXT SIZE DATA SIZE nsh> -o set +o set [{+|-}{e|x|xe|ex}] [ ] - Set the environment variable to the sting . - For example, + Set the environment variable to the sting and or set NSH + parser control options. For example, nsh> echo $foobar @@ -1029,6 +1029,38 @@ o set foovalue nsh> + Set the 'exit on error control' and/or 'print a trace' of commands when parsing + scripts in NSH. The settinngs are in effect from the point of exection, until + they are changed again, or in the case of the init script, the settings are + returned to the default settings when it exits. Included child scripts will run + with the parents settings and changes made in the child script will effect the + parent on return. + + Use 'set -e' to enable and 'set +e' to disable (ignore) the exit condition on commands. + The default is -e. Errors cause script to exit. + + Use 'set -x' to enable and 'set +x' to disable (silence) printing a trace of the script + commands as they are ececuted. + The default is +x. No printing of a trace of script commands as they are executed. + + Example 1 - no exit on command not found + set +e + notacommand + + Example 2 - will exit on command not found + set -e + notacommand + + Example 3 - will exit on command not found, and print a trace of the script commmands + set -ex + + Example 4 - will exit on command not found, and print a trace of the script commmands + and set foobar to foovalue. + set -ex foobar foovalue + nsh> echo $foobar + foovalue + + o sh Execute the sequence of NSH commands in the file referred diff --git a/nshlib/nsh.h b/nshlib/nsh.h index 25ef9ce46..6ce5bbf35 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -690,6 +690,15 @@ # undef NSH_HAVE_TRIMSPACES #endif +#ifndef CONFIG_NSH_DISABLESCRIPT +# define NSH_NP_SET_OPTIONS "ex" /* Maintain order see nsh_npflags_e */ +# define NSH_NP_SET_OPTIONS_INIT (NSH_PFALG_SILENT) +#endif + +#if defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_NSH_DISABLESCRIPT) +# define CONFIG_NSH_DISABLE_SET +#endif + /**************************************************************************** * Public Types ****************************************************************************/ @@ -741,6 +750,22 @@ struct nsh_loop_s }; #endif +#ifndef CONFIG_NSH_DISABLESCRIPT +/* Define the bits that correspond to the option defined in + * NSH_NP_SET_OPTIONS. The bit value is 1 shifted left the offset + * of the char in NSH_NP_SET_OPTIONS string. + */ + +enum nsh_npflags_e +{ + NSH_PFALG_IGNORE = 1, /* set for +e no exit on errors, + * cleared -e exit on error */ + NSH_PFALG_SILENT = 2, /* cleared -x print a trace of commands + * when parsing. + * set +x no print a trace of commands */ +}; +#endif + /* These structure provides the overall state of the parser */ struct nsh_parser_s @@ -752,6 +777,9 @@ struct nsh_parser_s 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_flags; /* See nsh_npflags_e above */ +#endif #ifndef CONFIG_NSH_DISABLEBG int np_nice; /* "nice" value applied to last background cmd */ #endif @@ -1175,10 +1203,10 @@ int cmd_lsmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); int cmd_uname(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif -#ifndef CONFIG_DISABLE_ENVIRON -# ifndef CONFIG_NSH_DISABLE_SET +#ifndef CONFIG_NSH_DISABLE_SET int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); -# endif +#endif +#ifndef CONFIG_DISABLE_ENVIRON # ifndef CONFIG_NSH_DISABLE_UNSET int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); # endif diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index ad68fd7c9..2d8b731d2 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -436,10 +436,14 @@ static const struct cmdmap_s g_cmdmap[] = { "rmmod", cmd_rmmod, 2, 2, "" }, #endif -#ifndef CONFIG_DISABLE_ENVIRON -# ifndef CONFIG_NSH_DISABLE_SET +#ifndef CONFIG_NSH_DISABLE_SET +# if !defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT) + { "set", cmd_set, 2, 4, "[{+|-}{e|x|xe|ex}] [ ]" }, +# elif !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_NSH_DISABLESCRIPT) { "set", cmd_set, 3, 3, " " }, -# endif +# elif defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT) + { "set", cmd_set, 2, 2, "{+|-}{e|x|xe|ex}" }, +# endif #endif #if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT) diff --git a/nshlib/nsh_console.c b/nshlib/nsh_console.c index 6d68e3acb..1a22f0a66 100644 --- a/nshlib/nsh_console.c +++ b/nshlib/nsh_console.c @@ -480,5 +480,11 @@ FAR struct console_stdio_s *nsh_newconsole(void) #endif } +#ifndef CONFIG_NSH_DISABLESCRIPT + /* Set the initial option flags */ + + pstate->cn_vtbl.np.np_flags = NSH_NP_SET_OPTIONS_INIT; +#endif + return pstate; } diff --git a/nshlib/nsh_consolemain.c b/nshlib/nsh_consolemain.c index f89944ff6..b61cf15af 100644 --- a/nshlib/nsh_consolemain.c +++ b/nshlib/nsh_consolemain.c @@ -85,6 +85,12 @@ int nsh_consolemain(int argc, char *argv[]) /* Execute the start-up script */ (void)nsh_initscript(&pstate->cn_vtbl); + +#ifndef CONFIG_NSH_DISABLESCRIPT + /* Reset the option flags */ + + pstate->cn_vtbl.np.np_flags = NSH_NP_SET_OPTIONS_INIT; +#endif #endif #ifdef CONFIG_NSH_USBDEV_TRACE diff --git a/nshlib/nsh_envcmds.c b/nshlib/nsh_envcmds.c index cbda78ba1..b323d9538 100644 --- a/nshlib/nsh_envcmds.c +++ b/nshlib/nsh_envcmds.c @@ -311,29 +311,86 @@ int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) * Name: cmd_set ****************************************************************************/ -#ifndef CONFIG_DISABLE_ENVIRON #ifndef CONFIG_NSH_DISABLE_SET int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { FAR char *value; - int ret; + int ret = OK; + int ndx = 1; +#ifndef CONFIG_NSH_DISABLESCRIPT + FAR char *popt; + const char opts[] = NSH_NP_SET_OPTIONS; + int op; - /* Trim whitespace from the value */ + /* Support set [{+|-}{e|x|xe|ex}] [ ] */ - value = nsh_trimspaces(argv[2]); - - /* Set the environment variable */ - - ret = setenv(argv[1], value, TRUE); - if (ret < 0) + if (argc == 2 || argc == 4) { - nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO); - } + if (strlen(argv[1]) < 2) + { + ret = -EINVAL; + nsh_output(vtbl, g_fmtargrequired, argv[0], "set", NSH_ERRNO); + } + else + { + op = argv[1][0]; + if (op != '-' && op != '+') + { + ret = -EINVAL; + nsh_output(vtbl, g_fmtarginvalid, argv[0], "set", NSH_ERRNO); + } + else + { + value = &argv[1][1]; + while(*value && *value != ' ') + { + popt = strchr(opts, *value++); + if (popt == NULL) + { + nsh_output(vtbl, g_fmtarginvalid, argv[0], "set", NSH_ERRNO); + ret = -EINVAL; + break; + } + if (op == '+') + { + vtbl->np.np_flags |= 1 << (popt-opts); + } + else + { + vtbl->np.np_flags &= ~(1 << (popt-opts)); + } + } + + if (ret == OK) + { + ndx = 2; + } + } + } + } +# ifndef CONFIG_DISABLE_ENVIRON + if (ret == OK && (argc == 3 || argc == 4)) +# endif +#endif +#ifndef CONFIG_DISABLE_ENVIRON + { + /* Trim whitespace from the value */ + + value = nsh_trimspaces(argv[ndx+1]); + + /* Set the environment variable */ + + ret = setenv(argv[ndx], value, TRUE); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO); + } + } +#endif return ret; } #endif -#endif /**************************************************************************** * Name: cmd_unset diff --git a/nshlib/nsh_script.c b/nshlib/nsh_script.c index 2c4a369bd..cc20a82ed 100644 --- a/nshlib/nsh_script.c +++ b/nshlib/nsh_script.c @@ -136,10 +136,15 @@ int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, * considerable amount of stack may be used. */ + if ((vtbl->np.np_flags & NSH_PFALG_SILENT) == 0) + { + nsh_output(vtbl,"%s", buffer); + } + ret = nsh_parse(vtbl, buffer); } } - while (pret && ret == OK); + while (pret && (ret == OK || (vtbl->np.np_flags & NSH_PFALG_IGNORE))); /* Close the script file */