summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib/unsetenv.c
diff options
context:
space:
mode:
authortron <tron@NetBSD.org>2010-09-25 18:11:40 +0000
committertron <tron@NetBSD.org>2010-09-25 18:11:40 +0000
commit5cdca2e60020da2dfd58990aada65b6d71aab939 (patch)
treed558847cd606f13e38a295044af4770a0d99a4d0 /lib/libc/stdlib/unsetenv.c
parent15ed98d439d987f17cc3d8d7e7a1d20194be0586 (diff)
Remember memory used by allocated environment variables instead of
using a bitmap. This deals with the case where a variable is first set via setenv(3) or putenv(3), then overwritten by changing "environ" directory and afterwards overwritten with setenv(3) again. This stops "zsh" from crashing under NetBSD-current. Code reviewed by Christos Zoulas.
Diffstat (limited to 'lib/libc/stdlib/unsetenv.c')
-rw-r--r--lib/libc/stdlib/unsetenv.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/lib/libc/stdlib/unsetenv.c b/lib/libc/stdlib/unsetenv.c
index 8fa4f40b267..1b67e56796e 100644
--- a/lib/libc/stdlib/unsetenv.c
+++ b/lib/libc/stdlib/unsetenv.c
@@ -1,4 +1,4 @@
-/* $NetBSD: unsetenv.c,v 1.5 2010/09/24 14:34:44 christos Exp $ */
+/* $NetBSD: unsetenv.c,v 1.6 2010/09/25 18:11:40 tron Exp $ */
/*
* Copyright (c) 1987, 1993
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "from: @(#)setenv.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: unsetenv.c,v 1.5 2010/09/24 14:34:44 christos Exp $");
+__RCSID("$NetBSD: unsetenv.c,v 1.6 2010/09/25 18:11:40 tron Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -53,10 +53,8 @@ __RCSID("$NetBSD: unsetenv.c,v 1.5 2010/09/24 14:34:44 christos Exp $");
* Delete environmental variable "name".
*/
int
-unsetenv(name)
- const char *name;
+unsetenv(const char *name)
{
- char **p;
int offset;
_DIAGASSERT(name != NULL);
@@ -66,22 +64,22 @@ unsetenv(name)
return -1;
}
- rwlock_wrlock(&__environ_lock);
+ if (rwlock_wrlock(&__environ_lock) != 0)
+ return -1;
if (__allocenv(-1) == -1)
return -1;
- while (__findenv(name, &offset)) { /* if set multiple times */
- if (bit_test(__environ_malloced, offset))
- free(environ[offset]);
- for (p = &environ[offset];; ++p, ++offset) {
- if (bit_test(__environ_malloced, offset + 1))
- bit_set(__environ_malloced, offset);
- else
- bit_clear(__environ_malloced, offset);
- if (!(*p = *(p + 1)))
- break;
+ while (__findenv(name, &offset) != NULL ) { /* if set multiple times */
+ free(__environ_malloced[offset]);
+
+ while (environ[offset] != NULL) {
+ environ[offset] = environ[offset + 1];
+ __environ_malloced[offset] =
+ __environ_malloced[offset + 1];
+ offset++;
}
+ __environ_malloced[offset] = NULL;
}
rwlock_unlock(&__environ_lock);