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:
Garance A Drosehn 2005-07-13 15:56:30 +00:00
parent 106e24aa5b
commit b5418f5134

37
usr.bin/env/envopts.c vendored
View File

@ -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);
}