diff --git a/nshlib/nsh_parse.c b/nshlib/nsh_parse.c index 6018fd894..9162a90bf 100644 --- a/nshlib/nsh_parse.c +++ b/nshlib/nsh_parse.c @@ -157,9 +157,9 @@ static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, #endif static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, - FAR char **allocation); + FAR char **allocation, int* isenvvar); static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr, - FAR NSH_MEMLIST_TYPE *memlist); + FAR NSH_MEMLIST_TYPE *memlist, int* isenvvar); #ifndef CONFIG_NSH_DISABLESCRIPT #ifndef CONFIG_NSH_DISABLE_LOOPS @@ -1010,7 +1010,7 @@ static FAR char *nsh_envexpand(FAR struct nsh_vtbl_s *vtbl, #if defined(CONFIG_NSH_ARGCAT) && defined(HAVE_MEMLIST) static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, - FAR char **allocation) + FAR char **allocation, int* isenvvar) { FAR char *working = cmdline; FAR char *argument = NULL; @@ -1129,8 +1129,8 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, *allocation = argument; /* Find the end of the environment variable reference. If the - * dollar sign ('$') is followed by a right bracket ('{') then the - * variable name is terminated with the left bracket character + * dollar sign ('$') is followed by a left bracket ('{') then the + * variable name is terminated with the right bracket character * ('}'). Otherwise, the variable name goes to the end of the * argument. */ @@ -1168,6 +1168,10 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, * nsh_envexpand will return the NULL string. */ + if (isenvvar) { + *isenvvar = 1; + } + envstr = nsh_envexpand(vtbl, ptr); #ifndef CONFIG_NSH_DISABLESCRIPT @@ -1199,7 +1203,7 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, #else static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, - FAR char **allocation) + FAR char **allocation, int* isenvvar) { FAR char *argument = (FAR char *)g_nullstring; @@ -1235,6 +1239,9 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, if (*cmdline == '$') { + if (isenvvar) { + *isenvvar = 1; + } argument = nsh_envexpand(vtbl, cmdline + 1); } else @@ -1257,7 +1264,7 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, ****************************************************************************/ static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr, - FAR NSH_MEMLIST_TYPE *memlist) + FAR NSH_MEMLIST_TYPE *memlist, int* isenvvar) { FAR char *pbegin = *saveptr; FAR char *pend = NULL; @@ -1330,6 +1337,13 @@ static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr, pbegin++; term = "\""; + + /* If this is an environment variable in double quotes, we don't want it split into + * multiple argument should CONFIG_NSH_ENABLEPX4PARSING be defined + * So just invalidate the flag pointer which would otherwise communictate such + * back up the call tree. + */ + isenvvar = NULL; } else { @@ -1400,11 +1414,11 @@ static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr, /* Perform expansions as necessary for the argument */ - argument = nsh_argexpand(vtbl, pbegin, &allocation); + argument = nsh_argexpand(vtbl, pbegin, &allocation, isenvvar); } /* 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 + * added to the list of memory to be freed at the end of command * processing. */ @@ -1521,7 +1535,7 @@ static int nsh_loop(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, /* Get the cmd following the "while" or "until" */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); if (!*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "if"); @@ -1578,7 +1592,7 @@ static int nsh_loop(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the "do" -- there may or may not be one */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); /* Verify that "do" is valid in this context */ @@ -1598,7 +1612,7 @@ static int nsh_loop(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the "done" -- there should be one */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); if (*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "done"); @@ -1703,7 +1717,7 @@ static int nsh_itef(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the if */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); if (!*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "if"); @@ -1741,7 +1755,7 @@ static int nsh_itef(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the "then" -- there may or may not be one */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); /* Verify that "then" is valid in this context */ @@ -1760,7 +1774,7 @@ static int nsh_itef(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the "else" -- there may or may not be one */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); /* Verify that "else" is valid in this context */ @@ -1779,7 +1793,7 @@ static int nsh_itef(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, { /* Get the cmd following the fi -- there should be one */ - *ppcmd = nsh_argument(vtbl, saveptr, memlist); + *ppcmd = nsh_argument(vtbl, saveptr, memlist, 0); if (*ppcmd) { nsh_output(vtbl, g_fmtarginvalid, "fi"); @@ -1851,10 +1865,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, memlist); + cmd = nsh_argument(vtbl, saveptr, memlist, 0); if (cmd && strcmp(cmd, "-d") == 0) { - FAR char *val = nsh_argument(vtbl, saveptr, memlist); + FAR char *val = nsh_argument(vtbl, saveptr, memlist, 0); if (val) { char *endptr; @@ -1865,7 +1879,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, memlist); + cmd = nsh_argument(vtbl, saveptr, memlist, 0); } } @@ -1935,7 +1949,7 @@ static int nsh_parse_cmdparm(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, &memlist); + cmd = nsh_argument(vtbl, &saveptr, &memlist, 0); /* Check if any command was provided -OR- if command processing is * currently disabled. @@ -1969,7 +1983,7 @@ static int nsh_parse_cmdparm(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, &memlist); + argv[argc] = nsh_argument(vtbl, &saveptr, &memlist, 0); if (!argv[argc]) { break; @@ -2036,7 +2050,7 @@ 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, &memlist); + cmd = nsh_argument(vtbl, &saveptr, &memlist, 0); #ifndef CONFIG_NSH_DISABLESCRIPT #ifndef CONFIG_NSH_DISABLE_LOOPS @@ -2104,15 +2118,54 @@ static int nsh_parse_command(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline) */ argv[0] = cmd; + +#define CONFIG_NSH_ENABLEPX4PARSING + for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++) { - argv[argc] = nsh_argument(vtbl, &saveptr, &memlist); + int isenvvar = 0; /* flag for if an enviroment variable gets expanded */ + argv[argc] = nsh_argument(vtbl, &saveptr, &memlist, &isenvvar); if (!argv[argc]) { break; } + +#ifdef CONFIG_NSH_ENABLEPX4PARSING + if (isenvvar) + { + while (argc < MAX_ARGV_ENTRIES-1) /* TODO: check this bounds check is correct */ + { + FAR char *pbegin = argv[argc]; + + /* Find the end of the current token */ + for (; *pbegin && !strchr(g_token_separator, *pbegin); pbegin++); + + /* If end of string, we've processed the last token and we're done */ + if ('\0' == *pbegin) + { + break; + } + + /* Terminate the token to complete the argv variable */ + *pbegin = '\0'; + + /* We've inserted an extra parameter, so bump the count */ + argc++; + + /* Move to the next character in the string of tokens */ + pbegin++; + + /* Throw away any extra separator chars between tokens */ + for (; *pbegin && strchr(g_token_separator, *pbegin) != NULL; pbegin++); + + /* Prepare to loop again on the next argument token */ + argv[argc] = pbegin; + } + } +#endif /* CONFIG_NSH_ENABLEPX4PARSING */ } + /* Last argument vector must be empty */ argv[argc] = NULL; /* Check if the command should run in background */