Deleted Added
full compact
36c36
< __FBSDID("$FreeBSD: head/lib/libc/stdlib/getenv.c 171195 2007-07-04 00:00:41Z scf $");
---
> __FBSDID("$FreeBSD: head/lib/libc/stdlib/getenv.c 171525 2007-07-20 23:30:13Z scf $");
38a39,44
> static const char CorruptEnvFindMsg[] =
> "environment corrupt; unable to find %.*s";
> static const char CorruptEnvValueMsg[] =
> "environment corrupt; missing value for %s";
>
>
45a52,53
> * intEnviron: Internally-built environ. Exposed via environ during
> * (re)builds of the environment.
48a57
> static char **intEnviron = NULL;
87c96
< static void __attribute__ ((destructor)) __clean_env(void);
---
> static void __attribute__ ((destructor)) __clean_env_destructor(void);
175a185,242
> * Remove variable added by putenv() from variable tracking array.
> */
> static void
> __remove_putenv(int envNdx)
> {
> envVarsTotal--;
> if (envVarsTotal > envNdx)
> memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]),
> (envVarsTotal - envNdx) * sizeof (*envVars));
> memset(&(envVars[envVarsTotal]), 0, sizeof (*envVars));
>
> return;
> }
>
>
> /*
> * Deallocate the environment built from environ as well as environ then set
> * both to NULL. Eases debugging of memory leaks.
> */
> static void
> __clean_env(bool freeVars)
> {
> int envNdx;
>
> /* Deallocate environment and environ if created by *env(). */
> if (envVars != NULL) {
> for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--)
> /* Free variables or deactivate them. */
> if (envVars[envNdx].putenv) {
> if (!freeVars)
> __remove_putenv(envNdx);
> } else {
> if (freeVars)
> free(envVars[envNdx].name);
> else
> envVars[envNdx].active = false;
> }
> if (freeVars) {
> free(envVars);
> envVars = NULL;
> } else
> envActive = 0;
>
> /* Restore original environ if it has not updated by program. */
> if (origEnviron != NULL) {
> if (environ == intEnviron)
> environ = origEnviron;
> free(intEnviron);
> intEnviron = NULL;
> environSize = 0;
> }
> }
>
> return;
> }
>
>
> /*
190c257
< tmpEnviron = realloc(environ, sizeof (*environ) *
---
> tmpEnviron = realloc(intEnviron, sizeof (*intEnviron) *
195c262
< environ = tmpEnviron;
---
> intEnviron = tmpEnviron;
202,203c269,270
< environ[environNdx++] = envVars[envNdx].name;
< environ[environNdx] = NULL;
---
> intEnviron[environNdx++] = envVars[envNdx].name;
> intEnviron[environNdx] = NULL;
204a272,274
> /* Always set environ which may have been replaced by program. */
> environ = intEnviron;
>
244d313
< int rtrnVal;
249c318
< if (environ == NULL)
---
> if (environ == NULL || environ[0] == NULL)
251,252d319
< if (environ[0] == NULL)
< goto SaveEnviron;
277,278c344
< warnx("environment corrupt; missing value for %s",
< envVars[envNdx].name);
---
> warnx(CorruptEnvValueMsg, envVars[envNdx].name);
293,294c359
< warnx("environment corrupt; unable to find %.*s",
< nameLen, envVars[envNdx].name);
---
> warnx(CorruptEnvFindMsg, nameLen, envVars[envNdx].name);
302d366
< SaveEnviron:
305,313c369,370
< if (envVarsTotal > 0) {
< rtrnVal = __rebuild_environ(envVarsTotal);
< if (rtrnVal == -1) {
< savedErrno = errno;
< __clean_env();
< errno = savedErrno;
< }
< } else
< rtrnVal = 0;
---
> if (__rebuild_environ(envVarsTotal) == 0)
> return (0);
315,316d371
< return (rtrnVal);
<
319c374
< __clean_env();
---
> __clean_env(true);
327c382
< * Remove variable added by putenv() from variable tracking array.
---
> * Destructor function with default argument to __clean_env().
330c385
< __remove_putenv(int envNdx)
---
> __clean_env_destructor(void)
332,334c387
< memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]),
< (envVarsTotal - envNdx) * sizeof (*envVars));
< envVarsTotal--;
---
> __clean_env(true);
341,368d393
< * Deallocate the environment built from environ as well as environ then set
< * both to NULL. Eases debugging of memory leaks.
< */
< static void
< __clean_env(void)
< {
< int envNdx;
<
< /* Deallocate environment and environ if created by *env(). */
< if (envVars != NULL) {
< for (envNdx = 0; envNdx < envVarsTotal; envNdx++)
< if (!envVars[envNdx].putenv)
< free(envVars[envNdx].name);
< free(envVars);
< envVars = NULL;
<
< /* Restore original environ. */
< if (origEnviron != NULL) {
< free(environ);
< environ = origEnviron;
< }
< }
<
< return;
< }
<
<
< /*
383,384c408,413
< /* Find environment variable via environ or rebuilt environment. */
< if (envVars == NULL)
---
> /*
> * Find environment variable via environ if no changes have been made
> * via a *env() call or environ has been replaced by a running program,
> * otherwise, use the rebuilt environment.
> */
> if (envVars == NULL || environ != intEnviron)
397a427,429
> *
> * The variables nameLen and valueLen are passed into here to allow the caller
> * to calculate the length by means besides just strlen().
399,400c431,432
< int
< setenv(const char *name, const char *value, int overwrite)
---
> static int
> __setenv(const char *name, size_t nameLen, const char *value, int overwrite)
406d437
< size_t nameLen;
409,418d439
< /* Check for malformed name. */
< if (name == NULL || (nameLen = __strleneq(name)) == 0) {
< errno = EINVAL;
< return (-1);
< }
<
< /* Initialize environment. */
< if (envVars == NULL && __build_env() == -1)
< return (-1);
<
440d460
<
483c503,568
< * Insert a "name=value" string into then environment. Special settings must be
---
> * If the program attempts to replace the array of environment variables
> * (environ) environ, then deactivate all variables and merge in the new list
> * from environ.
> */
> static int
> __merge_environ(void)
> {
> char **env;
> char *equals;
>
> /* environ has been replaced. clean up everything. */
> if (envVarsTotal > 0 && environ != intEnviron) {
> /* Deactivate all environment variables. */
> if (envActive > 0) {
> origEnviron = NULL;
> __clean_env(false);
> }
>
> /*
> * Insert new environ into existing, yet deactivated,
> * environment array.
> */
> origEnviron = environ;
> if (origEnviron != NULL)
> for (env = origEnviron; *env != NULL; env++) {
> if ((equals = strchr(*env, '=')) == NULL) {
> warnx(CorruptEnvValueMsg, *env);
> errno = EFAULT;
> return (-1);
> }
> if (__setenv(*env, equals - *env, equals + 1,
> 1) == -1)
> return (-1);
> }
> }
>
> return (0);
> }
>
>
> /*
> * The exposed setenv() that peforms a few tests before calling the function
> * (__setenv()) that does the actual work of inserting a variable into the
> * environment.
> */
> int
> setenv(const char *name, const char *value, int overwrite)
> {
> size_t nameLen;
>
> /* Check for malformed name. */
> if (name == NULL || (nameLen = __strleneq(name)) == 0) {
> errno = EINVAL;
> return (-1);
> }
>
> /* Initialize environment. */
> if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))
> return (-1);
>
> return (__setenv(name, nameLen, value, overwrite));
> }
>
>
> /*
> * Insert a "name=value" string into the environment. Special settings must be
503c588
< if (envVars == NULL && __build_env() == -1)
---
> if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))
555c640
< if (envVars == NULL && __build_env() == -1)
---
> if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))