--- setenv.c.orig 2003-05-20 15:23:25.000000000 -0700 +++ setenv.c 2004-11-05 17:15:11.000000000 -0800 @@ -40,81 +40,137 @@ #include <stddef.h> #include <stdlib.h> #include <string.h> +#include <crt_externs.h> +#include <errno.h> char *__findenv(const char *, int *); +__private_extern__ int __setenv(const char *, const char *, int, int); -/* - * setenv -- - * Set the value of the environmental variable "name" to be - * "value". If rewrite is set, replace any current value. - */ -int -setenv(name, value, rewrite) +#ifndef BUILDING_VARIANT +__private_extern__ int +__setenv(name, value, rewrite, copy) const char *name; const char *value; - int rewrite; + int rewrite, copy; { - extern char **environ; + char ***environp = _NSGetEnviron(); static char **alloced; /* if allocated space before */ char *c; - int l_value, offset; + int offset; - if (*value == '=') /* no `=' in value */ - ++value; - l_value = strlen(value); if ((c = __findenv(name, &offset))) { /* find if already exists */ if (!rewrite) return (0); - if (strlen(c) >= l_value) { /* old larger; copy over */ - while ( (*c++ = *value++) ); - return (0); - } + /* In UNIX03, we can't overwrite even if the string is long + * enough, because the putenv() string is owned by the user + * (ie, always malloc() a new string) */ } else { /* create new slot */ int cnt; char **p; - for (p = environ, cnt = 0; *p; ++p, ++cnt); - if (alloced == environ) { /* just increase size */ - p = (char **)realloc((char *)environ, + for (p = *environp, cnt = 0; *p; ++p, ++cnt); + if (alloced == *environp) { /* just increase size */ + p = (char **)realloc((char *)*environp, (size_t)(sizeof(char *) * (cnt + 2))); if (!p) return (-1); - alloced = environ = p; + alloced = *environp = p; } else { /* get new space */ /* copy old entries into it */ p = malloc((size_t)(sizeof(char *) * (cnt + 2))); if (!p) return (-1); - bcopy(environ, p, cnt * sizeof(char *)); - alloced = environ = p; + bcopy(*environp, p, cnt * sizeof(char *)); + alloced = *environp = p; } - environ[cnt + 1] = NULL; + (*environp)[cnt + 1] = NULL; offset = cnt; } - for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ - if (!(environ[offset] = /* name + `=' + value */ - malloc((size_t)((int)(c - name) + l_value + 2)))) - return (-1); - for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); - for (*c++ = '='; (*c++ = *value++); ); + /* For non Unix03, or UnixO3 setenv(), we make a copy of the user's + * strings. For Unix03 putenv(), we put the string directly in + * the environment. */ + if (copy) { + for (c = (char *)name; *c && *c != '='; ++c); /* no `=' in name */ + if (!((*environp)[offset] = /* name + `=' + value */ + malloc((size_t)((int)(c - name) + strlen(value) + 2)))) + return (-1); + for (c = (*environp)[offset]; (*c = *name++) && *c != '='; ++c); + for (*c++ = '='; (*c++ = *value++); ); + } else + (*environp)[offset] = name; return (0); } +#endif /* !BUILD_VARIANT */ + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +int +setenv(name, value, rewrite) + const char *name; + const char *value; + int rewrite; +{ + /* no null ptr or empty str */ + if(name == NULL || *name == 0) { + errno = EINVAL; + return (-1); + } + +#if __DARWIN_UNIX03 + /* no '=' in name */ + if (strchr(name, '=')) { + errno = EINVAL; + return (-1); + } +#endif /* __DARWIN_UNIX03 */ + + if (*value == '=') /* no `=' in value */ + ++value; + return (__setenv(name, value, rewrite, 1)); +} /* * unsetenv(name) -- * Delete environmental variable "name". */ +#if __DARWIN_UNIX03 +int +#else /* !__DARWIN_UNIX03 */ void +#endif /* __DARWIN_UNIX03 */ unsetenv(name) const char *name; { - extern char **environ; + char **environ = *_NSGetEnviron(); char **p; int offset; +#if __DARWIN_UNIX03 + /* no null ptr or empty str */ + if(name == NULL || *name == 0) { + errno = EINVAL; + return (-1); + } + + /* no '=' in name */ + if (strchr(name, '=')) { + errno = EINVAL; + return (-1); + } +#else /* !__DARWIN_UNIX03 */ + /* no null ptr or empty str */ + if(name == NULL || *name == 0) + return; +#endif /* __DARWIN_UNIX03 */ while (__findenv(name, &offset)) /* if set multiple times */ for (p = &environ[offset];; ++p) if (!(*p = *(p + 1))) break; +#if __DARWIN_UNIX03 + return 0; +#endif /* __DARWIN_UNIX03 */ }