summaryrefslogtreecommitdiff
path: root/libc/stdlib/setenv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/stdlib/setenv.c')
-rw-r--r--libc/stdlib/setenv.c62
1 files changed, 26 insertions, 36 deletions
diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c
index 15fac7448..3011f34a9 100644
--- a/libc/stdlib/setenv.c
+++ b/libc/stdlib/setenv.c
@@ -46,17 +46,14 @@ static char **last_environ;
is then placed in the environment, while the argument of `putenv'
must be used directly. This is all complicated by the fact that we try
to reuse values once generated for a `setenv' call since we can never
- free the strings. */
-int __add_to_environ(const char *name, const char *value,
- char *combined, int replace) attribute_hidden;
-int __add_to_environ(const char *name, const char *value,
- char *combined, int replace)
+ free the strings. [in uclibc, we do not] */
+static int __add_to_environ(const char *name, const char *value,
+ int replace)
{
register char **ep;
register size_t size;
/* name may come from putenv() and thus may contain "=VAL" part */
const size_t namelen = strchrnul(name, '=') - name;
- const size_t vallen = value != NULL ? strlen(value) + 1 : 0;
int rv = -1;
__UCLIBC_MUTEX_LOCK(mylock);
@@ -89,38 +86,30 @@ int __add_to_environ(const char *name, const char *value,
}
last_environ = __environ = new_environ;
- if (combined != NULL) {
- /* If the whole "VAR=VAL" is given, add it. */
- /* We must not add the string to the search tree
- * since it belongs to the user.
- * [glibc comment, uclibc doesnt track ptrs] */
- new_environ[size] = combined;
- } else {
- /* Build new "VAR=VAL" string. */
- new_environ[size] = malloc(namelen + 1 + vallen);
- if (new_environ[size] == NULL) {
- __set_errno(ENOMEM);
- goto DONE;
- }
- memcpy(new_environ[size], name, namelen);
- new_environ[size][namelen] = '=';
- memcpy(&new_environ[size][namelen + 1], value, vallen);
- }
- new_environ[size + 1] = NULL;
+ ep = &new_environ[size];
+ /* Ensure env is NULL terminated in case malloc below fails */
+ ep[0] = NULL;
+ ep[1] = NULL;
+ replace = 1;
+ }
+
+ if (replace) {
+ char *var_val = (char*) name;
+
+ /* Build VAR=VAL if we called by setenv, not putenv. */
+ if (value != NULL) {
+ const size_t vallen = strlen(value) + 1;
- } else if (replace) {
- /* Build the name if needed. */
- if (combined == NULL) {
- combined = malloc(namelen + 1 + vallen);
- if (combined == NULL) {
+ var_val = malloc(namelen + 1 + vallen);
+ if (var_val == NULL) {
__set_errno(ENOMEM);
goto DONE;
}
- memcpy(combined, name, namelen);
- combined[namelen] = '=';
- memcpy(&combined[namelen + 1], value, vallen);
+ memcpy(var_val, name, namelen);
+ var_val[namelen] = '=';
+ memcpy(&var_val[namelen + 1], value, vallen);
}
- *ep = combined;
+ *ep = var_val;
}
rv = 0;
@@ -133,7 +122,8 @@ int __add_to_environ(const char *name, const char *value,
/* libc_hidden_proto(setenv) */
int setenv(const char *name, const char *value, int replace)
{
- return __add_to_environ(name, value, NULL, replace);
+ /* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */
+ return __add_to_environ(name, value ? value : "", replace);
}
libc_hidden_def(setenv)
@@ -183,7 +173,7 @@ int clearenv(void)
* and is safe to free(). */
free(last_environ);
last_environ = NULL;
- /* Clear the environment pointer removes the whole environment. */
+ /* Clearing environ removes the whole environment. */
__environ = NULL;
__UCLIBC_MUTEX_UNLOCK(mylock);
return 0;
@@ -193,7 +183,7 @@ int clearenv(void)
int putenv(char *string)
{
if (strchr(string, '=') != NULL) {
- return __add_to_environ(string, NULL, string, 1);
+ return __add_to_environ(string, NULL, 1);
}
return unsetenv(string);
}