Fix setenv/putenv

diff --git a/klibc/Makefile b/klibc/Makefile
index c5d2227..49cd43b 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -33,7 +33,8 @@
 	  strsep.o strtok.o \
 	  gethostname.o getdomainname.o getcwd.o \
 	  seteuid.o setegid.o setresuid.o setresgid.o \
-	  getenv.o setenv.o unsetenv.o getopt.o readdir.o \
+	  getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
+	  getopt.o readdir.o \
 	  syslog.o closelog.o pty.o isatty.o reboot.o \
 	  time.o utime.o fdatasync.o llseek.o select.o nice.o getpriority.o \
 	  qsort.o lrand48.o srand48.o seed48.o \
diff --git a/klibc/__put_env.c b/klibc/__put_env.c
new file mode 100644
index 0000000..7e55f2c
--- /dev/null
+++ b/klibc/__put_env.c
@@ -0,0 +1,60 @@
+/*
+ * __put_env.c - common code for putenv() and setenv()
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Initialized to zero, meaning "not malloc'd" */
+static size_t __environ_size;
+
+/* 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)
+{
+  char **p, *q;
+  char **newenv;
+  size_t n;
+
+  n = 1;			/* Include space for final NULL */
+  for ( p = environ ; (q = *p) ; p++ ) {
+    n++;
+    if ( !strncmp(q,str,len) ) {
+      if ( !overwrite )
+	free(str);
+      else
+	*p = str;		/* Possible memory leak... */
+      return 0;
+    }
+  }
+
+  /* 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 ( !newenv )
+	return -1;
+
+      __environ_size <<= 1;
+    } else {
+      /* Make a reasonable guess how much more space we need */
+      size_t newsize = n+32;
+      newenv = malloc(newsize*sizeof(char *));
+      if ( !newenv )
+	return -1;
+
+      memcpy(newenv, environ, n*sizeof(char *));
+      __environ_size = newsize;
+    }
+    newenv[n-1] = str;		/* Old NULL position */
+    newenv[n]   = NULL;
+    environ = newenv;
+  }
+  return 0;
+}
diff --git a/klibc/putenv.c b/klibc/putenv.c
new file mode 100644
index 0000000..8138c65
--- /dev/null
+++ b/klibc/putenv.c
@@ -0,0 +1,40 @@
+/*
+ * putenv.c
+ */
+
+#include <errno.h>
+#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);
+
+int putenv(const char *str)
+{
+  char *s;
+  const char *e, *z;
+
+  if ( !str ) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  e = NULL;
+  for ( z = str ; *z ; z++ ) {
+    if ( *z == '=' )
+      e = z;
+  }
+
+  if ( !e ) {
+    errno = EINVAL;
+    return -1;
+  }
+
+  s = strdup(str);
+  if ( !s )
+    return -1;
+
+  return __put_env(s, e-str, 1);
+}
diff --git a/klibc/setenv.c b/klibc/setenv.c
index d1118ff..d4ada53 100644
--- a/klibc/setenv.c
+++ b/klibc/setenv.c
@@ -7,87 +7,9 @@
 #include <string.h>
 #include <unistd.h>
 
-/* Initialized to zero, meaning "not malloc'd" */
-static size_t __environ_size;
-
 /* str should be a duplicated version of the input string;
    len is the length of the key including the = sign */
-static int _putenv(char *str, size_t len, int overwrite)
-{
-  char **p, *q;
-  char **newenv;
-  size_t n;
-
-  n = 1;			/* Include space for final NULL */
-  for ( p = environ ; (q = *p) ; p++ ) {
-    n++;
-    if ( !strncmp(q,str,len) ) {
-      if ( overwrite )
-	free(str);
-      else
-	*p = str;		/* Memory leak... */
-      return 0;
-    }
-  }
-
-  /* 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 ( !newenv )
-	return -1;
-
-      __environ_size <<= 1;
-    } else {
-      /* Make a reasonable guess how much more space we need */
-      size_t newsize = n+32;
-      newenv = malloc(newsize*sizeof(char *));
-      if ( !newenv )
-	return -1;
-
-      memcpy(newenv, environ, n*sizeof(char *));
-      __environ_size = newsize;
-    }
-    newenv[n+1] = NULL;
-    newenv[n]   = str;
-    environ = newenv;
-  }
-  return 0;
-}
-
-int putenv(const char *str)
-{
-  char *s;
-  const char *e, *z;
-  size_t len;
-
-  if ( !str ) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  len = 0; e = NULL;
-  for ( z = str ; *z ; z++ ) {
-    len++;
-    if ( *z == '=' )
-      e = z;
-  }
-
-  if ( !e ) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  s = strdup(str);
-  if ( !s )
-    return -1;
-
-  return _putenv(s, len, 1);
-}
+int __put_env(char *str, size_t len, int overwrite);
 
 int setenv(const char *name, const char *val, int overwrite)
 {
@@ -117,8 +39,7 @@
 
   memcpy(s, name, l1);
   s[l1] = '=';
-  memcpy(s+l1+1, val, l2);
-  s[l1+l2+1] = '\0';
+  memcpy(s+l1+1, val, l2+1);
 
-  return _putenv(s, l1+1, overwrite);
+  return __put_env(s, l1+1, overwrite);
 }
diff --git a/klibc/tests/getenvtest.c b/klibc/tests/environ.c
similarity index 72%
rename from klibc/tests/getenvtest.c
rename to klibc/tests/environ.c
index 07cac0c..6eeeb91 100644
--- a/klibc/tests/getenvtest.c
+++ b/klibc/tests/environ.c
@@ -17,10 +17,8 @@
   }
 
   /* Test environ */
-  printf("PATH = %s\n", getenv("PATH"));
-  printf("HOME = %s\n", getenv("HOME"));
-  printf("TERM = %s\n", getenv("TERM"));
-  printf("USER = %s\n", getenv("USER"));
+  for ( i = 0 ; envp[i] ; i++ )
+    printf("%s\n", envp[i]);
 
   return 0;
 }
diff --git a/klibc/tests/setenvtest.c b/klibc/tests/setenvtest.c
new file mode 100644
index 0000000..111bef9
--- /dev/null
+++ b/klibc/tests/setenvtest.c
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+  (void)argc; (void)argv;
+
+  /* Set SETENV */
+  setenv("SETENV", "setenv", 1);
+
+  /* Set PUTENV */
+  putenv("PUTENV=putenv");
+
+  /* Print the results... */
+  printf("SETENV = %s\n", getenv("SETENV"));
+  printf("PUTENV = %s\n", getenv("PUTENV"));
+
+  /* Override tests */
+  setenv("SETENV", "setenv_good", 1);
+  putenv("PUTENV=putenv_good");
+  printf("SETENV = %s\n", getenv("SETENV"));
+  printf("PUTENV = %s\n", getenv("PUTENV"));
+
+  /* Non-override test */
+  setenv("SETENV", "setenv_bad", 0);
+  setenv("NEWENV", "newenv_good", 0);
+  printf("SETENV = %s\n", getenv("SETENV"));
+  printf("NEWENV = %s\n", getenv("NEWENV"));
+
+  /* Undef test */
+  unsetenv("SETENV");
+  unsetenv("NEWENV");
+  printf("SETENV = %s\n", getenv("SETENV"));
+  printf("NEWENV = %s\n", getenv("NEWENV"));
+
+  return 0;
+}