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...
This commit is contained in:
parent
106e24aa5b
commit
b5418f5134
37
usr.bin/env/envopts.c
vendored
37
usr.bin/env/envopts.c
vendored
@ -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 @@ split_spaces(const char *str, int *origind, int *origc, char ***origv)
|
||||
* 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user