From e9edfd064fe63cff3a6178488732dbd1b5b19beb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 1 Oct 2018 13:30:25 -0600 Subject: [PATCH] apps/nshlib: Add support for NSH local variables if CONFIG_NSH_VARS are set. These are like environment variables but are local to NSH. The importance of this is that these variables are *not* inherited when NSH creates a new task. The new command 'export' was added. In this case, the NSH variable will be promoted to an environment variable and will then be inherited by any tasks executed by NSH. --- nshlib/Kconfig | 49 +++++++++++++++--- nshlib/Make.defs | 1 - nshlib/Makefile | 4 ++ nshlib/README.txt | 88 ++++++++++++++++++++++--------- nshlib/nsh.h | 54 ++++++++++++++++--- nshlib/nsh_command.c | 10 ++-- nshlib/nsh_console.c | 12 ++++- nshlib/nsh_console.h | 7 +++ nshlib/nsh_envcmds.c | 121 +++++++++++++++++++++++++++++++++++++------ nshlib/nsh_parse.c | 49 +++++++++++------- 10 files changed, 318 insertions(+), 77 deletions(-) diff --git a/nshlib/Kconfig b/nshlib/Kconfig index 57b155859..f2911cdc4 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -18,12 +18,6 @@ config NSH_LIBRARY if NSH_LIBRARY -config NSH_PROMPT_STRING - string "Prompt String" - default "nsh> " - ---help--- - Provide the shell prompt string, default is "nsh> ". - menuconfig NSH_MOTD bool "Message of the Day (MOTD)" default n @@ -69,6 +63,12 @@ endif # NSH_MOTD menu "Command Line Configuration" +config NSH_PROMPT_STRING + string "Prompt String" + default "nsh> " + ---help--- + Provide the shell prompt string, default is "nsh> ". + choice prompt "Command Line Editor" default NSH_READLINE if DEFAULT_SMALL @@ -298,6 +298,10 @@ config NSH_DISABLE_EXIT default y if DEFAULT_SMALL && !NSH_TELNET default n if !DEFAULT_SMALL || NSH_TELNET +config NSH_DISABLE_EXPORT + bool "Disable export" + default n + config NSH_DISABLE_FREE bool "Disable free" default n @@ -597,6 +601,39 @@ endif # MMCSD menu "Configure Command Options" +config NSH_VARS + bool "NSH variables" + default n + ---help--- + By default, there are no internal NSH variables. NSH will use OS + environment variables for all variable storage. If this option, NSH + will also support local NSH variables. These variables are, for the + most part, transparent and work just like the OS environment + variables. The difference is that when you create new tasks, all of + environment variables are inherited by the created tasks. NSH local + variables are not. + + If this option is enabled (and CONFIG_DISABLE_ENVIRON is not), then a + new command called 'export' is enabled. The export command works very + must like the set command except that is operates on environment + variables. When CONFIG_NSH_VARS is enabled, there are changes in the + behavior of certains commands + + ============== =========================== =========================== + CMD w/o CONFIG_NSH_VARS w/CONFIG_NSH_VARS + ============== =========================== =========================== + set Set environment var a to b Set NSH var a to b + unset Unsets environment var a Unsets both environment var + and NSH var a + export Causes an error Unsets NSH var a. Sets + environment var a to b. + export Causes an error Sets environment var a to + NSH var b (or ""). Unsets + local var a. + env Lists all environment Lists all environment + variables variables + ============== =========================== =========================== + config NSH_CMDOPT_DD_STATS bool "dd: Support transfer statistics" default n diff --git a/nshlib/Make.defs b/nshlib/Make.defs index 97ec50a8e..61fd9a4e0 100644 --- a/nshlib/Make.defs +++ b/nshlib/Make.defs @@ -37,4 +37,3 @@ ifneq ($(CONFIG_NSH_LIBRARY),) CONFIGURED_APPS += nshlib endif - diff --git a/nshlib/Makefile b/nshlib/Makefile index a720dcfd2..3b2ada2a2 100644 --- a/nshlib/Makefile +++ b/nshlib/Makefile @@ -65,6 +65,10 @@ ifeq ($(CONFIG_NSH_FILE_APPS),y) CSRCS += nsh_fileapps.c endif +ifeq ($(CONFIG_NSH_VARS),y) +CSRCS += nsh_vars.c +endif + ifeq ($(CONFIG_NSH_ROMFSETC),y) CSRCS += nsh_romfsetc.c endif diff --git a/nshlib/README.txt b/nshlib/README.txt index a1eaf7d1b..fa2b8d508 100644 --- a/nshlib/README.txt +++ b/nshlib/README.txt @@ -483,7 +483,7 @@ o echo [-n] [ [...]] o env - Show the current address environment. Example: + Show the current name-value pairs in the environment. Example: nsh> env PATH=/bin @@ -499,6 +499,8 @@ o env nsh> + NOTE: NSH variables are *not* shown by the env command. + o exec Execute the user logic at address . NSH will pause @@ -511,6 +513,36 @@ o exit using the 'exec' command') and you would like to have NSH out of the way. +o export [] + + The 'export' command sets an environment variable, or promotes an + NSH variable to an environment variable. As examples: + + 1. Using 'export' to promote an NSH variable to an environment variable. + + nsh> env + PATH=/bin + + nsh> set foo bar + nsh> env + PATH=/bin + + nsh> export foo + nsh> env + PATH=/bin + foo=bar + + 2. Using 'export' to set an environment variable + + nsh> export dog poop + nsh> env + PATH=/bin + foo=bar + dog=poop + + The export is command is not supported by NSH unless both CONFIG_NSH_VARS=y + and CONFIG_DISABLE_ENVIRON is not set. + o free Show the current state of the memory allocator. For example, @@ -1072,8 +1104,10 @@ o route ipv4|ipv6 o set [{+|-}{e|x|xe|ex}] [ ] - Set the environment variable to the sting and or set NSH - parser control options. For example, + Set the variable to the sting and or set NSH parser control + options. + + For example, a variable may be set like this: nsh> echo $foobar @@ -1082,6 +1116,9 @@ o set [{+|-}{e|x|xe|ex}] [ ] foovalue nsh> + If CONFIG_NSH_VARS is set, the effect of the 'set' command is to set the local + NSH variable. Otherwise, the group-wide environment variable will be set. + 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 @@ -1113,7 +1150,6 @@ o set [{+|-}{e|x|xe|ex}] [ ] nsh> echo $foobar foovalue - o sh Execute the sequence of NSH commands in the file referred @@ -1227,8 +1263,9 @@ o umount o unset - Remove the value associated with the environment variable - . Example: + Remove the value associated with the variable . This will remove + the name-value pairt from both the NSH local variables and the group-wide + environment variables. For example: nsh> echo $foobar foovalue @@ -1368,6 +1405,7 @@ Command Dependencies on Configuration Settings env -- CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_PROCFS && !CONFIG_DISABLE_ENVIRON && !CONFIG_PROCFS_EXCLUDE_ENVIRON exec -- exit -- + export CONFIG_NSH_VARS && !CONFIG_DISABLE_ENVIRON free -- get CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && MTU >= 558 (see note 1) help -- @@ -1405,7 +1443,7 @@ Command Dependencies on Configuration Settings route CONFIG_FS_PROCFS && CONFIG_FS_PROCFS_EXCLUDE_NET && !CONFIG_FS_PROCFS_EXCLUDE_ROUTE && CONFIG_NET_ROUTE && !CONFIG_NSH_DISABLE_ROUTE && (CONFIG_NET_IPv4 || CONFIG_NET_IPv6) - set !CONFIG_DISABLE_ENVIRON + set CONFIG_NSH_VARS || !CONFIG_DISABLE_ENVIRON sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !CONFIG_NSH_DISABLESCRIPT shutdown CONFIG_BOARDCTL_POWEROFF || CONFIG_BOARDCTL_RESET sleep !CONFIG_DISABLE_SIGNALS @@ -1415,7 +1453,7 @@ Command Dependencies on Configuration Settings truncate !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 umount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE uname !CONFIG_NSH_DISABLE_UNAME - unset !CONFIG_DISABLE_ENVIRON + unset CONFIG_NSH_VARS || !CONFIG_DISABLE_ENVIRON urldecode CONFIG_NETUTILS_CODECS && CONFIG_CODECS_URLCODE urlencode CONFIG_NETUTILS_CODECS && CONFIG_CODECS_URLCODE useradd !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE && CONFIG_NSH_LOGIN_PASSWD @@ -1444,23 +1482,23 @@ also allow it to squeeze into very small memory footprints. CONFIG_NSH_DISABLE_CP, CONFIG_NSH_DISABLE_DD, CONFIG_NSH_DISABLE_DELROUTE, CONFIG_NSH_DISABLE_DF, CONFIG_NSH_DISABLE_DIRNAME, CONFIG_NSH_DISABLE_ECHO, CONFIG_NSH_DISABLE_ENV, CONFIG_NSH_DISABLE_EXEC, CONFIG_NSH_DISABLE_EXIT, - CONFIG_NSH_DISABLE_FREE, CONFIG_NSH_DISABLE_GET, CONFIG_NSH_DISABLE_HELP, - CONFIG_NSH_DISABLE_HEXDUMP, CONFIG_NSH_DISABLE_IFCONFIG, CONFIG_NSH_DISABLE_IFUPDOWN, - CONFIG_NSH_DISABLE_KILL, CONFIG_NSH_DISABLE_LOSETUP, CONFIG_NSH_DISABLE_LN, - CONFIG_NSH_DISABLE_LS, CONFIG_NSH_DISABLE_MD5, CONFIG_NSH_DISABLE_MB, - CONFIG_NSH_DISABLE_MKDIR, CONFIG_NSH_DISABLE_MKFATFS, CONFIG_NSH_DISABLE_MKFIFO, - CONFIG_NSH_DISABLE_MKRD, CONFIG_NSH_DISABLE_MH, CONFIG_NSH_DISABLE_MODCMDS, - CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, CONFIG_NSH_DISABLE_MV, - CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_NSLOOKUP, CONFIG_NSH_DISABLE_PASSWD, - CONFIG_NSH_DISABLE_PING6, CONFIG_NSH_DISABLE_POWEROFF, CONFIG_NSH_DISABLE_PS, - CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, CONFIG_NSH_DISABLE_READLINK, - CONFIG_NSH_DISABLE_REBOOT, CONFIG_NSH_DISABLE_RM, CONFIG_NSH_DISABLE_RMDIR, - CONFIG_NSH_DISABLE_ROUTE, CONFIG_NSH_DISABLE_SET, CONFIG_NSH_DISABLE_SH, - CONFIG_NSH_DISABLE_SHUTDOWN, CONFIG_NSH_DISABLE_SLEEP, CONFIG_NSH_DISABLE_TEST, - CONFIG_NSH_DIABLE_TIME, CONFIG_NSH_DISABLE_TRUNCATE, CONFIG_NSH_DISABLE_UMOUNT, - CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_URLDECODE, CONFIG_NSH_DISABLE_URLENCODE, - CONFIG_NSH_DISABLE_USERADD, CONFIG_NSH_DISABLE_USERDEL, CONFIG_NSH_DISABLE_USLEEP, - CONFIG_NSH_DISABLE_WGET, CONFIG_NSH_DISABLE_XD + CONFIG_NSH_DISABLE_EXPORT, CONFIG_NSH_DISABLE_FREE, CONFIG_NSH_DISABLE_GET, + CONFIG_NSH_DISABLE_HELP, CONFIG_NSH_DISABLE_HEXDUMP, CONFIG_NSH_DISABLE_IFCONFIG, + CONFIG_NSH_DISABLE_IFUPDOWN, CONFIG_NSH_DISABLE_KILL, CONFIG_NSH_DISABLE_LOSETUP, + CONFIG_NSH_DISABLE_LN, CONFIG_NSH_DISABLE_LS, CONFIG_NSH_DISABLE_MD5, + CONFIG_NSH_DISABLE_MB, CONFIG_NSH_DISABLE_MKDIR, CONFIG_NSH_DISABLE_MKFATFS, + CONFIG_NSH_DISABLE_MKFIFO, CONFIG_NSH_DISABLE_MKRD, CONFIG_NSH_DISABLE_MH, + CONFIG_NSH_DISABLE_MODCMDS, CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, + CONFIG_NSH_DISABLE_MV, CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_NSLOOKUP, + CONFIG_NSH_DISABLE_PASSWD, CONFIG_NSH_DISABLE_PING6, CONFIG_NSH_DISABLE_POWEROFF, + CONFIG_NSH_DISABLE_PS, CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, + CONFIG_NSH_DISABLE_READLINK, CONFIG_NSH_DISABLE_REBOOT, CONFIG_NSH_DISABLE_RM, + CONFIG_NSH_DISABLE_RMDIR, CONFIG_NSH_DISABLE_ROUTE, CONFIG_NSH_DISABLE_SET, + CONFIG_NSH_DISABLE_SH, CONFIG_NSH_DISABLE_SHUTDOWN, CONFIG_NSH_DISABLE_SLEEP, + CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DIABLE_TIME, CONFIG_NSH_DISABLE_TRUNCATE, + CONFIG_NSH_DISABLE_UMOUNT, CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_URLDECODE, + CONFIG_NSH_DISABLE_URLENCODE, CONFIG_NSH_DISABLE_USERADD, CONFIG_NSH_DISABLE_USERDEL, + CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET, CONFIG_NSH_DISABLE_XD Verbose help output can be suppressed by defining CONFIG_NSH_HELP_TERSE. In that case, the help command is still available but will be slightly smaller. diff --git a/nshlib/nsh.h b/nshlib/nsh.h index ad56f6049..98c593977 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -544,6 +544,11 @@ # define CONFIG_LIB_HOMEDIR "/" #endif +#undef NSH_HAVE_VARS +#if defined(CONFIG_NSH_VARS) || !defined(CONFIG_DISABLE_ENVIRON) +# define NSH_HAVE_VARS +#endif + /* Stubs used when working directory is not supported */ #if CONFIG_NFILE_DESCRIPTORS <= 0 || defined(CONFIG_DISABLE_ENVIRON) @@ -683,6 +688,11 @@ # define CONFIG_NSH_DISABLE_ENV 1 #endif +#if !defined(CONFIG_NSH_VARS) || defined(CONFIG_DISABLE_ENVIRON) +# undef CONFIG_NSH_DISABLE_EXPORT +# define CONFIG_NSH_DISABLE_EXPORT 1 +#endif + /* nsh_catfile used by cat, ifconfig, ifup/down, df, free, env, irqinfo, and * mount (with no arguments). */ @@ -721,9 +731,11 @@ # define NSH_NP_SET_OPTIONS_INIT (NSH_PFLAG_SILENT) #endif -#if defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_NSH_DISABLESCRIPT) +#if !defined(NSH_HAVE_VARS) && defined(CONFIG_NSH_DISABLESCRIPT) # undef CONFIG_NSH_DISABLE_SET # define CONFIG_NSH_DISABLE_SET 1 +# undef CONFIG_NSH_DISABLE_UNSET +# define CONFIG_NSH_DISABLE_UNSET 1 #endif /**************************************************************************** @@ -1015,6 +1027,9 @@ void nsh_usbtrace(void); #ifndef CONFIG_NSH_DISABLE_EXEC int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif +#ifndef CONFIG_NSH_DISABLE_EXPORT + int cmd_export(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif #ifndef CONFIG_NSH_DISABLE_MB int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif @@ -1247,13 +1262,12 @@ int cmd_env(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif #ifndef CONFIG_NSH_DISABLE_SET - int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); + int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif + +#ifndef CONFIG_NSH_DISABLE_UNSET + int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif -#ifndef CONFIG_DISABLE_ENVIRON -# ifndef CONFIG_NSH_DISABLE_UNSET - int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); -# endif -#endif /* CONFIG_DISABLE_ENVIRON */ #ifndef CONFIG_DISABLE_SIGNALS # ifndef CONFIG_NSH_DISABLE_KILL @@ -1444,4 +1458,30 @@ void nsh_trimdir(FAR char *dirpath); FAR char *nsh_trimspaces(FAR char *str); #endif +/**************************************************************************** + * Name: nsh_getvar and nsh_setvar + * + * Description: + * Get or set an NSH variable. + * + * Input Parmeters: + * vtbl - NSH session data + * name - The name of the variable to get or set + * + * Returned value: + * nsh_getvar() returns a read-only reference to the variable value on + * success or NULL on failure. + * nset_unsetvar() returns OK on success or an netaged errno value on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NSH_VARS +FAR const char *nsh_getvar(FAR struct nsh_vtbl_s *vtbl, + FAR const char *name); +int nsh_setvar(FAR struct nsh_vtbl_s *vtbl, FAR const char *name, + FAR const char *value); +int nsh_unsetvar(FAR struct nsh_vtbl_s *vtbl, FAR const char *name); +#endif + #endif /* __APPS_NSHLIB_NSH_H */ diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index aa32b8ee4..ae728b49b 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -204,8 +204,12 @@ static const struct cmdmap_s g_cmdmap[] = { "exit", cmd_exit, 1, 1, NULL }, #endif +#ifndef CONFIG_NSH_DISABLE_EXPORT + { "export", cmd_export, 2, 3, "[ []]" }, +#endif + #ifndef CONFIG_NSH_DISABLESCRIPT - { "false", cmd_false, 1, 1, NULL }, + { "false", cmd_false, 1, 1, NULL }, #endif #ifndef CONFIG_NSH_DISABLE_FREE @@ -517,10 +521,8 @@ static const struct cmdmap_s g_cmdmap[] = # endif #endif -#ifndef CONFIG_DISABLE_ENVIRON -# ifndef CONFIG_NSH_DISABLE_UNSET +#ifndef CONFIG_NSH_DISABLE_UNSET { "unset", cmd_unset, 2, 2, "" }, -# endif #endif #if defined(CONFIG_NETUTILS_CODECS) && defined(CONFIG_CODECS_URLCODE) diff --git a/nshlib/nsh_console.c b/nshlib/nsh_console.c index 36a72782a..ad36b398d 100644 --- a/nshlib/nsh_console.c +++ b/nshlib/nsh_console.c @@ -307,6 +307,15 @@ static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl) #endif #endif +#ifdef CONFIG_NSH_VARS + /* Free any NSH variables */ + + if (pstate->varp != NULL) + { + free(pstate->varp); + } +#endif + /* Then release the vtable container */ free(pstate); @@ -343,7 +352,8 @@ 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) +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 serialsave_s *ssave = (FAR struct serialsave_s *)save; diff --git a/nshlib/nsh_console.h b/nshlib/nsh_console.h index d51cf206e..a2d606f8d 100644 --- a/nshlib/nsh_console.h +++ b/nshlib/nsh_console.h @@ -158,6 +158,13 @@ struct console_stdio_s FILE *cn_outstream; /* Output stream */ #endif +#ifdef CONFIG_NSH_VARS + /* Allocation and size of NSH variables */ + + FAR char *varp; + size_t varsz; +#endif + /* Line input buffer */ char cn_line[CONFIG_NSH_LINELEN]; diff --git a/nshlib/nsh_envcmds.c b/nshlib/nsh_envcmds.c index 526a7dd05..ffb2823a1 100644 --- a/nshlib/nsh_envcmds.c +++ b/nshlib/nsh_envcmds.c @@ -201,9 +201,9 @@ void nsh_freefullpath(FAR char *fullpath) #ifndef CONFIG_NSH_DISABLE_CD int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { - const char *path = argv[1]; - char *alloc = NULL; - char *fullpath = NULL; + FAR const char *path = argv[1]; + FAR char *alloc = NULL; + FAR char *fullpath = NULL; int ret = OK; /* Check for special arguments */ @@ -228,7 +228,7 @@ int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) path = fullpath; } - /* Set the new workding directory */ + /* Set the new working directory */ ret = chdir(path); if (ret != 0) @@ -327,15 +327,18 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { FAR char *value; int ret = OK; -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef NSH_HAVE_VARS int ndx = 1; #endif + #ifndef CONFIG_NSH_DISABLESCRIPT FAR char *popt; const char opts[] = NSH_NP_SET_OPTIONS; int op; -#ifndef CONFIG_DISABLE_ENVIRON + /* REVISIT: set with no arguments should show all of the NSH variables */ + +#ifdef NSH_HAVE_VARS /* Support set [{+|-}{e|x|xe|ex}] [ ] */ if (argc == 2 || argc == 4) @@ -380,7 +383,7 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) } } -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef NSH_HAVE_VARS if (ret == OK) { ndx = 2; @@ -390,16 +393,27 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) } } -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef NSH_HAVE_VARS if (ret == OK && (argc == 3 || argc == 4)) #endif #endif /* CONFIG_NSH_DISABLESCRIPT */ -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef NSH_HAVE_VARS { /* Trim whitespace from the value */ value = nsh_trimspaces(argv[ndx+1]); +#if defined(CONFIG_NSH_VARS) + /* Set NSH variable (may shadow a environment variable) */ + + ret = nsh_setvar(vtbl, argv[ndx], value); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "nsh_setvar", + NSH_ERRNO_OF(-ret)); + } + +#elif !defined(CONFIG_DISABLE_ENVIRON) /* Set the environment variable */ ret = setenv(argv[ndx], value, TRUE); @@ -407,27 +421,104 @@ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO); } - } #endif + } +#endif /* NSH_HAVE_VARS */ + return ret; } -#endif +#endif /* CONFIG_NSH_DISABLE_SET */ /**************************************************************************** * Name: cmd_unset ****************************************************************************/ -#ifndef CONFIG_DISABLE_ENVIRON #ifndef CONFIG_NSH_DISABLE_UNSET int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { - int ret = unsetenv(argv[1]); - if (ret < 0) + int status; + int ret = OK; + +#if defined(CONFIG_NSH_VARS) + /* Unset NSH variable */ + + status = nsh_unsetvar(vtbl, argv[1]); + if (status < 0 && status != -ENOENT) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "nsh_unsetvar", + NSH_ERRNO_OF(-status)); + ret = ERROR; + } +#endif + +#if !defined(CONFIG_DISABLE_ENVIRON) + /* Unset environment variable */ + + status = unsetenv(argv[1]); + if (status < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO); + ret = ERROR; } +#endif return ret; } #endif -#endif + +/**************************************************************************** + * Name: cmd_export + ****************************************************************************/ + +#ifndef CONFIG_NSH_DISABLE_UNSET +int cmd_export(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + FAR const char *value = ""; + int status; + int ret = OK; + + /* Get the value from the command line if provided. argc may be either 2 + * or 3 + */ + + if (argc == 3) + { + value = argv[2]; + } + else + { + FAR const char *tmp; + + /* Try to get the value from the NSH variable */ + + tmp = nsh_getvar(vtbl, argv[1]); + if (tmp != NULL) + { + value = tmp; + } + } + + /* Set the environment variable to the selected value */ + + status = setenv(argv[1], value, TRUE); + if (status < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO); + ret = ERROR; + } + else + { + /* Unset NSH variable */ + + status = nsh_unsetvar(vtbl, argv[1]); + if (status < 0 && status != -ENOENT) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "nsh_unsetvar", + NSH_ERRNO_OF(-status)); + ret = ERROR; + } + } + + return ret; +} +#endif \ No newline at end of file diff --git a/nshlib/nsh_parse.c b/nshlib/nsh_parse.c index b51fc2b4a..c10c07564 100644 --- a/nshlib/nsh_parse.c +++ b/nshlib/nsh_parse.c @@ -158,8 +158,8 @@ static FAR char *nsh_strchr(FAR const char *str, int ch); # define nsh_strchr(s,c) strchr(s,c) #endif -#ifndef CONFIG_DISABLE_ENVIRON -static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, +#ifdef NSH_HAVE_VARS +static FAR const char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *varname); #endif @@ -217,7 +217,7 @@ static const char g_arg_separator[] = "`$"; #endif static const char g_redirect1[] = ">"; static const char g_redirect2[] = ">>"; -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef CONFIG_NSH_VARS static const char g_exitstatus[] = "?"; static const char g_success[] = "0"; static const char g_failure[] = "1"; @@ -1013,9 +1013,9 @@ static FAR char *nsh_strchr(FAR const char *str, int ch) * Name: nsh_envexpand ****************************************************************************/ -#ifndef CONFIG_DISABLE_ENVIRON -static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, - FAR char *varname) +#ifdef NSH_HAVE_VARS +static FAR const char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, + FAR char *varname) { /* Check for built-in variables */ @@ -1030,22 +1030,35 @@ static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, return (FAR char *)g_success; } } - - /* Not a built-in? Return the value of the environment variable with this - * name. - */ - else { - FAR char *value = getenv(varname); - if (value) + FAR const char *value; + + /* Not a built-in? Return the value of the NSH variable with this + * name. + */ + +#ifdef CONFIG_NSH_VARS + value = nsh_getvar(vtbl, varname); + if (value != NULL) { return value; } - else +#endif + + /* Not an NSH variable? Return the value of the NSH variable environment variable with this + * name. + */ + +#ifndef CONFIG_DISABLE_ENVIRON + value = getenv(varname); + if (value != NULL) { - return (FAR char *)g_nullstring; + return value; } +#endif + + return (FAR char *)g_nullstring; } } #endif @@ -1256,12 +1269,12 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, else #endif -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef CONFIG_NSH_VARS /* Check if we encountered a reference to an environment variable */ if (*ptr == '$') { - FAR char *envstr; + FAR const char *envstr; FAR char *rptr; /* Replace the dollar sign with a NUL terminator and add the @@ -1397,7 +1410,7 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, else #endif -#ifndef CONFIG_DISABLE_ENVIRON +#ifdef NSH_HAVE_VARS /* Check for references to environment variables */ if (*cmdline == '$')