|
@@ -47,115 +47,116 @@ static char **last_environ;
|
|
|
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,
|
|
|
- const char *combined, int replace) attribute_hidden;
|
|
|
-int __add_to_environ (const char *name, const char *value,
|
|
|
- const char *combined, int replace)
|
|
|
+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)
|
|
|
{
|
|
|
- register char **ep;
|
|
|
- register size_t size;
|
|
|
- const size_t namelen = strlen (name);
|
|
|
- const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
|
|
|
- int rv = -1;
|
|
|
+ register char **ep;
|
|
|
+ register size_t size;
|
|
|
+
|
|
|
+ const size_t namelen = strchrnul(name, '=') - name;
|
|
|
+ const size_t vallen = value != NULL ? strlen(value) + 1 : 0;
|
|
|
+ int rv = -1;
|
|
|
|
|
|
- __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
|
|
|
-
|
|
|
- since another thread might have created a new environment. */
|
|
|
- ep = __environ;
|
|
|
+
|
|
|
+ since another thread might have created a new environment. */
|
|
|
+ ep = __environ;
|
|
|
|
|
|
- size = 0;
|
|
|
- if (ep != NULL) {
|
|
|
+ size = 0;
|
|
|
+ if (ep != NULL) {
|
|
|
for (; *ep != NULL; ++ep) {
|
|
|
- if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
|
|
|
+ if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=')
|
|
|
break;
|
|
|
- else
|
|
|
- ++size;
|
|
|
+ ++size;
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if (ep == NULL || *ep == NULL) {
|
|
|
+ if (ep == NULL || *ep == NULL) {
|
|
|
+
|
|
|
char **new_environ;
|
|
|
|
|
|
|
|
|
- new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *));
|
|
|
+ new_environ = realloc(last_environ, (size + 2) * sizeof(char *));
|
|
|
if (new_environ == NULL) {
|
|
|
+ __set_errno(ENOMEM);
|
|
|
goto DONE;
|
|
|
}
|
|
|
+ if (__environ != last_environ) {
|
|
|
+ memcpy(new_environ, __environ, size * sizeof(char *));
|
|
|
+ }
|
|
|
+ last_environ = __environ = new_environ;
|
|
|
|
|
|
-
|
|
|
if (combined != NULL) {
|
|
|
-
|
|
|
- to the user. */
|
|
|
- new_environ[size] = (char *) combined;
|
|
|
+
|
|
|
+
|
|
|
+ * since it belongs to the user.
|
|
|
+ * [glibc comment, uclibc doesnt track ptrs] */
|
|
|
+ new_environ[size] = combined;
|
|
|
} else {
|
|
|
-
|
|
|
- new_environ[size] = (char *) malloc (namelen + 1 + vallen);
|
|
|
+
|
|
|
+ new_environ[size] = malloc(namelen + 1 + vallen);
|
|
|
if (new_environ[size] == NULL) {
|
|
|
- __set_errno (ENOMEM);
|
|
|
+ __set_errno(ENOMEM);
|
|
|
goto DONE;
|
|
|
}
|
|
|
-
|
|
|
- memcpy (new_environ[size], name, namelen);
|
|
|
+ memcpy(new_environ[size], name, namelen);
|
|
|
new_environ[size][namelen] = '=';
|
|
|
- memcpy (&new_environ[size][namelen + 1], value, vallen);
|
|
|
- }
|
|
|
-
|
|
|
- if (__environ != last_environ) {
|
|
|
- memcpy ((char *) new_environ, (char *) __environ,
|
|
|
- size * sizeof (char *));
|
|
|
+ memcpy(&new_environ[size][namelen + 1], value, vallen);
|
|
|
}
|
|
|
-
|
|
|
new_environ[size + 1] = NULL;
|
|
|
- last_environ = __environ = new_environ;
|
|
|
- } else if (replace) {
|
|
|
- char *np;
|
|
|
|
|
|
-
|
|
|
- if (combined != NULL) {
|
|
|
- np = (char *) combined;
|
|
|
- } else {
|
|
|
- np = malloc (namelen + 1 + vallen);
|
|
|
- if (np == NULL) {
|
|
|
+ } else if (replace) {
|
|
|
+
|
|
|
+ if (combined == NULL) {
|
|
|
+ combined = malloc(namelen + 1 + vallen);
|
|
|
+ if (combined == NULL) {
|
|
|
+ __set_errno(ENOMEM);
|
|
|
goto DONE;
|
|
|
}
|
|
|
- memcpy (np, name, namelen);
|
|
|
- np[namelen] = '=';
|
|
|
- memcpy (&np[namelen + 1], value, vallen);
|
|
|
+ memcpy(combined, name, namelen);
|
|
|
+ combined[namelen] = '=';
|
|
|
+ memcpy(&combined[namelen + 1], value, vallen);
|
|
|
}
|
|
|
- *ep = np;
|
|
|
- }
|
|
|
+ *ep = combined;
|
|
|
+ }
|
|
|
|
|
|
- rv = 0;
|
|
|
+ rv = 0;
|
|
|
|
|
|
DONE:
|
|
|
- __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
- return rv;
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ return rv;
|
|
|
}
|
|
|
|
|
|
|
|
|
-int setenv (const char *name, const char *value, int replace)
|
|
|
+int setenv(const char *name, const char *value, int replace)
|
|
|
{
|
|
|
- return __add_to_environ (name, value, NULL, replace);
|
|
|
+ return __add_to_environ(name, value, NULL, replace);
|
|
|
}
|
|
|
libc_hidden_def(setenv)
|
|
|
|
|
|
|
|
|
-int unsetenv (const char *name)
|
|
|
+int unsetenv(const char *name)
|
|
|
{
|
|
|
- size_t len;
|
|
|
- char **ep;
|
|
|
-
|
|
|
- if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) {
|
|
|
- __set_errno (EINVAL);
|
|
|
+ const char *eq;
|
|
|
+ size_t len;
|
|
|
+ char **ep;
|
|
|
+
|
|
|
+ if (name == NULL || *name == '\0'
|
|
|
+ || *(eq = strchrnul(name, '=')) == '='
|
|
|
+ ) {
|
|
|
+ __set_errno(EINVAL);
|
|
|
return -1;
|
|
|
- }
|
|
|
-
|
|
|
- len = strlen (name);
|
|
|
- __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
- ep = __environ;
|
|
|
- while (*ep != NULL) {
|
|
|
- if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
|
|
|
+ }
|
|
|
+ len = eq - name;
|
|
|
+
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ ep = __environ;
|
|
|
+
|
|
|
+ if (ep) while (*ep != NULL) {
|
|
|
+ if (!strncmp(*ep, name, len) && (*ep)[len] == '=') {
|
|
|
|
|
|
char **dp = ep;
|
|
|
do {
|
|
@@ -165,42 +166,34 @@ int unsetenv (const char *name)
|
|
|
} else {
|
|
|
++ep;
|
|
|
}
|
|
|
- }
|
|
|
- __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
- return 0;
|
|
|
+ }
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ return 0;
|
|
|
}
|
|
|
libc_hidden_def(unsetenv)
|
|
|
|
|
|
|
|
|
never made it. Nevertheless the POSIX.9 standard (POSIX bindings
|
|
|
for Fortran 77) requires this function. */
|
|
|
-int clearenv (void)
|
|
|
+int clearenv(void)
|
|
|
{
|
|
|
- __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
- if (__environ == last_environ && __environ != NULL) {
|
|
|
-
|
|
|
- free (__environ);
|
|
|
- last_environ = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- __environ = NULL;
|
|
|
- __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
- return 0;
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+
|
|
|
+ * If we did not allocate this environment, it's NULL already
|
|
|
+ * and is safe to free(). */
|
|
|
+ free(last_environ);
|
|
|
+ last_environ = NULL;
|
|
|
+
|
|
|
+ __environ = NULL;
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
-int putenv (char *string)
|
|
|
+int putenv(char *string)
|
|
|
{
|
|
|
- int result;
|
|
|
- const char *const name_end = strchr (string, '=');
|
|
|
-
|
|
|
- if (name_end != NULL) {
|
|
|
- char *name = strndup(string, name_end - string);
|
|
|
- result = __add_to_environ (name, NULL, string, 1);
|
|
|
- free(name);
|
|
|
- return(result);
|
|
|
- }
|
|
|
- unsetenv (string);
|
|
|
- return 0;
|
|
|
+ if (strchr(string, '=') != NULL) {
|
|
|
+ return __add_to_environ(string, NULL, string, 1);
|
|
|
+ }
|
|
|
+ return unsetenv(string);
|
|
|
}
|
|
|
-
|