diff options
Diffstat (limited to 'sysdeps/generic/setenv.c')
-rw-r--r-- | sysdeps/generic/setenv.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c index 1907a2b..dc2e8b4 100644 --- a/sysdeps/generic/setenv.c +++ b/sysdeps/generic/setenv.c @@ -16,24 +16,36 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ansidecl.h> +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> + +#if _LIBC || HAVE_STDLIB_H #include <stdlib.h> +#endif +#if _LIBC || HAVE_STRING_H #include <string.h> +#endif +#if _LIBC || HAVE_UNISTD_H #include <unistd.h> -#include <errno.h> +#endif #ifndef HAVE_GNU_LD #define __environ environ #endif int -DEFUN(setenv, (name, value, replace), - CONST char *name AND CONST char *value AND int replace) +setenv (name, value, replace) + const char *name; + const char *value; + int replace; { register char **ep; register size_t size; - CONST size_t namelen = strlen (name); - CONST size_t vallen = strlen (value); + const size_t namelen = strlen (name); + const size_t vallen = strlen (value) + 1; size = 0; for (ep = __environ; *ep != NULL; ++ep) @@ -41,38 +53,47 @@ DEFUN(setenv, (name, value, replace), break; else ++size; - + if (*ep == NULL) { - static char **last_environ = NULL; - char **new_environ = (char **) malloc((size + 2) * sizeof(char *)); + static char **last_environ; + char **new_environ; + if (__environ == last_environ) + /* We allocated this space; we can extend it. */ + new_environ = (char **) realloc (last_environ, + (size + 2) * sizeof (char *)); + else + new_environ = (char **) malloc ((size + 2) * sizeof (char *)); + if (new_environ == NULL) return -1; - (void) memcpy((PTR) new_environ, (PTR) __environ, size * sizeof(char *)); - new_environ[size] = malloc (namelen + 1 + vallen + 1); + new_environ[size] = malloc (namelen + 1 + vallen); if (new_environ[size] == NULL) { - free (new_environ); + free ((char *) new_environ); errno = ENOMEM; return -1; } + + if (__environ != last_environ) + memcpy ((char *) new_environ, (char *) __environ, + size * sizeof (char *)); + memcpy (new_environ[size], name, namelen); new_environ[size][namelen] = '='; - memcpy (&new_environ[size][namelen + 1], value, vallen + 1); + memcpy (&new_environ[size][namelen + 1], value, vallen); new_environ[size + 1] = NULL; - if (last_environ != NULL) - free ((PTR) last_environ); - last_environ = new_environ; - __environ = new_environ; + last_environ = __environ = new_environ; } else if (replace) { size_t len = strlen (*ep); - if (len < namelen + 1 + vallen) + if (len + 1 < namelen + 1 + vallen) { + /* The existing string is too short; malloc a new one. */ char *new = malloc (namelen + 1 + vallen); if (new == NULL) return -1; @@ -80,8 +101,26 @@ DEFUN(setenv, (name, value, replace), } memcpy (*ep, name, namelen); (*ep)[namelen] = '='; - memcpy (&(*ep)[namelen + 1], value, vallen + 1); + memcpy (&(*ep)[namelen + 1], value, vallen); } return 0; } + +void +unsetenv (const char *name) +{ + const size_t len = strlen (name); + char **ep; + + for (ep = __environ; *ep; ++ep) + if (!strncmp (*ep, name, len) && (*ep)[len] == '=') + { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + do + dp[0] = dp[1]; + while (*dp++); + /* Continue the loop in case NAME appears again. */ + } +} |