summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2005-07-13 15:56:30 +0000
committergad <gad@FreeBSD.org>2005-07-13 15:56:30 +0000
commit4aa994cdc4a3fae188b5b39a0e70206ad0249d30 (patch)
treef3e601740313f01777547f525075dd9efaebfcd2
parentfa4b3709bb561c7765f5f22cd3e7fc5637122f5a (diff)
downloadFreeBSD-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...
-rw-r--r--usr.bin/env/envopts.c37
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);
}
OpenPOWER on IntegriCloud