diff options
author | gad <gad@FreeBSD.org> | 2005-07-13 15:56:30 +0000 |
---|---|---|
committer | gad <gad@FreeBSD.org> | 2005-07-13 15:56:30 +0000 |
commit | 4aa994cdc4a3fae188b5b39a0e70206ad0249d30 (patch) | |
tree | f3e601740313f01777547f525075dd9efaebfcd2 /usr.bin/env | |
parent | fa4b3709bb561c7765f5f22cd3e7fc5637122f5a (diff) | |
download | FreeBSD-src-4aa994cdc4a3fae188b5b39a0e70206ad0249d30.zip FreeBSD-src-4aa994cdc4a3fae188b5b39a0e70206ad0249d30.tar.gz |
Fix two minor parsing bugs in -S processing:
1) An unquoted space is always a separator, even when not "in_arg".
2) When a new destination buffer must be allocated during variable
substitution, only copy data from the active buffer to the new
one when we *are* "in_arg".
These were noticed when testing variable-substitution of variables
which have null values, and are not inside quoted strings...
MFC plans: after a few days, and re@ approval...
Diffstat (limited to 'usr.bin/env')
-rw-r--r-- | usr.bin/env/envopts.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/usr.bin/env/envopts.c b/usr.bin/env/envopts.c index cf85b1f..c62da6d 100644 --- a/usr.bin/env/envopts.c +++ b/usr.bin/env/envopts.c @@ -44,8 +44,8 @@ __FBSDID("$FreeBSD$"); #include "envopts.h" static const char * - expand_vars(char **thisarg_p, char **dest_p, const char - **src_p); + expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, + const char **src_p); static int is_there(char *candidate); /* @@ -222,8 +222,8 @@ split_spaces(const char *str, int *origind, int *origc, char ***origv) if (in_sq) copychar = *src; else { - copystr = expand_vars((nextarg - 1), &dest, - &src); + copystr = expand_vars(in_arg, (nextarg - 1), + &dest, &src); } break; case '\'': @@ -315,7 +315,7 @@ split_spaces(const char *str, int *origind, int *origc, char ***origv) default: if ((in_dq || in_sq) && in_arg) copychar = *src; - else if (in_arg && isspacech(*src)) + else if (isspacech(*src)) found_sep = 1; else { /* @@ -386,7 +386,7 @@ str_done: * possibly *thisarg_p in the calling routine. */ static const char * -expand_vars(char **thisarg_p, char **dest_p, const char **src_p) +expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, const char **src_p) { const char *vbegin, *vend, *vvalue; char *newstr, *vname; @@ -441,15 +441,24 @@ expand_vars(char **thisarg_p, char **dest_p, const char **src_p) /* * The value is longer than the string it replaces, which means the * present destination area is too small to hold it. Create a new - * destination area, copy the present 'thisarg' value to it, and - * update the caller's 'thisarg' and 'dest' variables to match. - * Note that it is still the caller which will copy vvalue to *dest. + * destination area, and update the caller's 'dest' variable to match. + * If the caller has already started copying some info for 'thisarg' + * into the present destination, then the new destination area must + * include a copy of that data, and the pointer to 'thisarg' must also + * be updated. Note that it is still the caller which copies this + * vvalue to the new *dest. */ - **dest_p = '\0'; /* Provide terminator for 'thisarg' */ - newlen = strlen(*thisarg_p) + strlen(vvalue) + strlen(*src_p) + 1; - newstr = malloc(newlen); - strcpy(newstr, *thisarg_p); - *thisarg_p = newstr; + newlen = strlen(vvalue) + strlen(*src_p) + 1; + if (in_thisarg) { + **dest_p = '\0'; /* Provide terminator for 'thisarg' */ + newlen += strlen(*thisarg_p); + newstr = malloc(newlen); + strcpy(newstr, *thisarg_p); + *thisarg_p = newstr; + } else { + newstr = malloc(newlen); + *newstr = '\0'; + } *dest_p = strchr(newstr, '\0'); return (vvalue); } |