Merge with git+ssh://hera.kernel.org/pub/scm/libs/klibc/klibc.git
diff --git a/include/stdlib.h b/include/stdlib.h
index 17efc30..487bcda 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -47,6 +47,7 @@
__extern int putenv(const char *);
__extern int setenv(const char *, const char *, int);
__extern int unsetenv(const char *);
+__extern int clearenv(void);
__extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
diff --git a/klibc/Makefile b/klibc/Makefile
index bf32f7c..f7b8ac5 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -41,6 +41,7 @@
gethostname.o getdomainname.o getcwd.o \
seteuid.o setegid.o \
getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
+ clearenv.o nullenv.o \
getopt.o readdir.o \
syslog.o closelog.o pty.o getpt.o isatty.o reboot.o \
time.o utime.o llseek.o nice.o getpriority.o \
diff --git a/klibc/__put_env.c b/klibc/__put_env.c
index 7e55f2c..8ee12e9 100644
--- a/klibc/__put_env.c
+++ b/klibc/__put_env.c
@@ -6,18 +6,23 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "env.h"
-/* Initialized to zero, meaning "not malloc'd" */
static size_t __environ_size;
+static char **__environ_alloc;
/* str should be a duplicated version of the input string;
len is the length of the key including the = sign */
int __put_env(char *str, size_t len, int overwrite)
{
+ static char * const null_environ = { NULL };
char **p, *q;
char **newenv;
size_t n;
+ if ( !environ )
+ environ = (char **)null_environ;
+
n = 1; /* Include space for final NULL */
for ( p = environ ; (q = *p) ; p++ ) {
n++;
@@ -30,14 +35,19 @@
}
}
+ if ( __environ_alloc && environ != __environ_alloc ) {
+ free(__environ_alloc);
+ __environ_alloc = NULL;
+ }
+
/* Need to extend the environment */
if ( n < __environ_size ) {
p[1] = NULL;
*p = str;
return 0;
} else {
- if ( __environ_size ) {
- newenv = realloc(environ, (__environ_size << 1)*sizeof(char *));
+ if ( __environ_alloc ) {
+ newenv = realloc(__environ_alloc, (__environ_size << 1)*sizeof(char *));
if ( !newenv )
return -1;
diff --git a/klibc/clearenv.c b/klibc/clearenv.c
new file mode 100644
index 0000000..036b20f
--- /dev/null
+++ b/klibc/clearenv.c
@@ -0,0 +1,17 @@
+/*
+ * clearenv.c
+ *
+ * Empty the environment
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "env.h"
+
+/* Note: if environ has been malloc'd, it will be freed on the next
+ setenv() or putenv() */
+int clearenv(void)
+{
+ environ = (char **)__null_environ;
+ return 0;
+}
diff --git a/klibc/env.h b/klibc/env.h
new file mode 100644
index 0000000..8c70f94
--- /dev/null
+++ b/klibc/env.h
@@ -0,0 +1,10 @@
+#ifndef ENV_H
+#define ENV_H
+
+/* str should be a duplicated version of the input string;
+ len is the length of the key including the = sign */
+int __put_env(char *str, size_t len, int overwrite);
+
+extern char * const __null_environ[];
+
+#endif
diff --git a/klibc/getenv.c b/klibc/getenv.c
index 84fc94c..b90cb48 100644
--- a/klibc/getenv.c
+++ b/klibc/getenv.c
@@ -11,6 +11,9 @@
char **p, *q;
int len = strlen(name);
+ if ( !environ )
+ return NULL;
+
for ( p = environ ; (q = *p) ; p++ ) {
if ( !strncmp(name, q, len) && q[len] == '=' ) {
return q+(len+1);
diff --git a/klibc/nullenv.c b/klibc/nullenv.c
new file mode 100644
index 0000000..ba7e71c
--- /dev/null
+++ b/klibc/nullenv.c
@@ -0,0 +1,8 @@
+/*
+ * nullenv.c
+ */
+
+#include <stddef.h>
+#include "env.h"
+
+char * const __null_environ[] = { NULL };
diff --git a/klibc/putenv.c b/klibc/putenv.c
index 8138c65..3274fce 100644
--- a/klibc/putenv.c
+++ b/klibc/putenv.c
@@ -6,10 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-
-/* str should be a duplicated version of the input string;
- len is the length of the key including the = sign */
-int __put_env(char *str, size_t len, int overwrite);
+#include "env.h"
int putenv(const char *str)
{
diff --git a/klibc/setenv.c b/klibc/setenv.c
index d4ada53..b149954 100644
--- a/klibc/setenv.c
+++ b/klibc/setenv.c
@@ -6,10 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-
-/* str should be a duplicated version of the input string;
- len is the length of the key including the = sign */
-int __put_env(char *str, size_t len, int overwrite);
+#include "env.h"
int setenv(const char *name, const char *val, int overwrite)
{
diff --git a/klibc/unsetenv.c b/klibc/unsetenv.c
index 5f39f3d..61bd75f 100644
--- a/klibc/unsetenv.c
+++ b/klibc/unsetenv.c
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "env.h"
int unsetenv(const char *name)
{
@@ -27,6 +28,9 @@
}
}
+ if ( !environ )
+ return 0;
+
for ( p = environ ; (q = *p) ; p++ ) {
if ( !strncmp(name,q,len) && q[len] == '=' )
break;