Bug fixes; add readdir() and friends

diff --git a/atox.c b/atox.c
index a3acf6c..56f8d93 100644
--- a/atox.c
+++ b/atox.c
@@ -6,6 +6,7 @@
 
 #include <inttypes.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 TYPE NAME (const char *nptr)
 {
diff --git a/include/dirent.h b/include/dirent.h
new file mode 100644
index 0000000..034cd48
--- /dev/null
+++ b/include/dirent.h
@@ -0,0 +1,20 @@
+/*
+ * dirent.h
+ */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#include <extern.h>
+#include <sys/dirent.h>
+
+#ifndef __IO_DIR_DEFINED
+struct _IO_dir;
+#endif
+typedef struct _IO_dir DIR;
+
+__extern DIR *opendir(const char *);
+__extern struct dirent *readdir(DIR *);
+__extern int closedir(DIR *);
+
+#endif /* _DIRENT_H */
diff --git a/include/sys/dirent.h b/include/sys/dirent.h
index 61903b0..0700f4b 100644
--- a/include/sys/dirent.h
+++ b/include/sys/dirent.h
@@ -5,6 +5,7 @@
 #ifndef _SYS_DIRENT_H
 #define _SYS_DIRENT_H
 
+#include <sys/types.h>
 #include <linux/dirent.h>
 
 __extern int getdents(unsigned int, struct dirent *, unsigned int);
diff --git a/include/sys/mman.h b/include/sys/mman.h
index faf6491..7d53616 100644
--- a/include/sys/mman.h
+++ b/include/sys/mman.h
@@ -8,6 +8,7 @@
 #include <extern.h>
 #include <sys/types.h>
 #include <linux/mman.h>
+#include <asm/page.h>		/* For PAGE_SIZE */
 
 #define MAP_FAILED ((void *)-1)
 
diff --git a/klibc/Makefile b/klibc/Makefile
index b675047..c14bdf1 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -4,7 +4,8 @@
 LD      = $(CROSS)ld
 OPTFLAGS = -Os -fomit-frame-pointer -march=i386 -mcpu=i686 \
 	   -malign-functions=0 -malign-jumps=0 -malign-loops=0
-CFLAGS  = -nostdinc -iwithprefix include -I. -I./include -I./linux/include -Wall -g $(OPTFLAGS)
+CFLAGS  = -nostdinc -iwithprefix include -I. -I./include \
+	  -I./linux/include -Wall -g $(OPTFLAGS)
 LDFLAGS =
 AR      = $(CROSS)ar
 RANLIB  = $(CROSS)ranlib
@@ -29,7 +30,7 @@
 	  strcmp.o strcpy.o strdup.o strlen.o strncat.o strstr.o \
 	  strncmp.o strncpy.o strrchr.o strspn.o strsep.o strtok.o \
 	  gethostname.o getdomainname.o getcwd.o seteuid.o setegid.o \
-	  getenv.o setenv.o unsetenv.o getopt.o \
+	  getenv.o setenv.o unsetenv.o getopt.o readdir.o \
 	  time.o fdatasync.o
 LIB     = libc.a
 
diff --git a/klibc/atox.c b/klibc/atox.c
index a3acf6c..56f8d93 100644
--- a/klibc/atox.c
+++ b/klibc/atox.c
@@ -6,6 +6,7 @@
 
 #include <inttypes.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 TYPE NAME (const char *nptr)
 {
diff --git a/klibc/include/dirent.h b/klibc/include/dirent.h
new file mode 100644
index 0000000..034cd48
--- /dev/null
+++ b/klibc/include/dirent.h
@@ -0,0 +1,20 @@
+/*
+ * dirent.h
+ */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+#include <extern.h>
+#include <sys/dirent.h>
+
+#ifndef __IO_DIR_DEFINED
+struct _IO_dir;
+#endif
+typedef struct _IO_dir DIR;
+
+__extern DIR *opendir(const char *);
+__extern struct dirent *readdir(DIR *);
+__extern int closedir(DIR *);
+
+#endif /* _DIRENT_H */
diff --git a/klibc/include/sys/dirent.h b/klibc/include/sys/dirent.h
index 61903b0..0700f4b 100644
--- a/klibc/include/sys/dirent.h
+++ b/klibc/include/sys/dirent.h
@@ -5,6 +5,7 @@
 #ifndef _SYS_DIRENT_H
 #define _SYS_DIRENT_H
 
+#include <sys/types.h>
 #include <linux/dirent.h>
 
 __extern int getdents(unsigned int, struct dirent *, unsigned int);
diff --git a/klibc/include/sys/mman.h b/klibc/include/sys/mman.h
index faf6491..7d53616 100644
--- a/klibc/include/sys/mman.h
+++ b/klibc/include/sys/mman.h
@@ -8,6 +8,7 @@
 #include <extern.h>
 #include <sys/types.h>
 #include <linux/mman.h>
+#include <asm/page.h>		/* For PAGE_SIZE */
 
 #define MAP_FAILED ((void *)-1)
 
diff --git a/klibc/readdir.c b/klibc/readdir.c
new file mode 100644
index 0000000..f689d8a
--- /dev/null
+++ b/klibc/readdir.c
@@ -0,0 +1,66 @@
+/*
+ * opendir/readdir/closedir
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/dirent.h>
+#include <stdio.h>
+
+#define __IO_DIR_DEFINED
+struct _IO_dir {
+  int fd;
+  size_t bytes_left;
+  struct dirent *next;
+  struct dirent buffer[4];	/* 4 times max dirent size */
+};
+
+#include <dirent.h>
+
+DIR *opendir(const char *name)
+{
+  DIR *dp = malloc(sizeof(DIR));
+
+  if ( !dp )
+    return NULL;
+
+  dp->fd = open(name, O_DIRECTORY|O_RDONLY);
+
+  if ( dp->fd < 0 ) {
+    free(dp);
+    return NULL;
+  }
+
+  dp->bytes_left = 0;
+
+  return dp;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+  struct dirent *dent;
+  int rv;
+  
+  if ( !dir->bytes_left ) {
+    rv = getdents(dir->fd, dir->buffer, sizeof(dir->buffer));
+    if ( rv <= 0 )
+      return NULL;
+    dir->bytes_left = rv;
+    dir->next = dir->buffer;
+  }
+
+  dent = dir->next;
+  ((char *)dir->next) += dent->d_reclen;
+  dir->bytes_left -= dent->d_reclen;
+  
+  return dent;
+}
+
+int closedir(DIR *dir)
+{
+  int rv;
+  rv = close(dir->fd);
+  free(dir);
+  return rv;
+}
diff --git a/klibc/strntoumax.c b/klibc/strntoumax.c
index c515310..4e30637 100644
--- a/klibc/strntoumax.c
+++ b/klibc/strntoumax.c
@@ -11,7 +11,7 @@
 static inline int digitval(int ch)
 {
   if ( ch >= '0' && ch <= '9' ) {
-    return ch-'9';
+    return ch-'0';
   } else if ( ch >= 'A' && ch <= 'Z' ) {
     return ch-'A'+10;
   } else if ( ch >= 'a' && ch <= 'z' ) {
diff --git a/readdir.c b/readdir.c
new file mode 100644
index 0000000..f689d8a
--- /dev/null
+++ b/readdir.c
@@ -0,0 +1,66 @@
+/*
+ * opendir/readdir/closedir
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/dirent.h>
+#include <stdio.h>
+
+#define __IO_DIR_DEFINED
+struct _IO_dir {
+  int fd;
+  size_t bytes_left;
+  struct dirent *next;
+  struct dirent buffer[4];	/* 4 times max dirent size */
+};
+
+#include <dirent.h>
+
+DIR *opendir(const char *name)
+{
+  DIR *dp = malloc(sizeof(DIR));
+
+  if ( !dp )
+    return NULL;
+
+  dp->fd = open(name, O_DIRECTORY|O_RDONLY);
+
+  if ( dp->fd < 0 ) {
+    free(dp);
+    return NULL;
+  }
+
+  dp->bytes_left = 0;
+
+  return dp;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+  struct dirent *dent;
+  int rv;
+  
+  if ( !dir->bytes_left ) {
+    rv = getdents(dir->fd, dir->buffer, sizeof(dir->buffer));
+    if ( rv <= 0 )
+      return NULL;
+    dir->bytes_left = rv;
+    dir->next = dir->buffer;
+  }
+
+  dent = dir->next;
+  ((char *)dir->next) += dent->d_reclen;
+  dir->bytes_left -= dent->d_reclen;
+  
+  return dent;
+}
+
+int closedir(DIR *dir)
+{
+  int rv;
+  rv = close(dir->fd);
+  free(dir);
+  return rv;
+}
diff --git a/strntoumax.c b/strntoumax.c
index c515310..4e30637 100644
--- a/strntoumax.c
+++ b/strntoumax.c
@@ -11,7 +11,7 @@
 static inline int digitval(int ch)
 {
   if ( ch >= '0' && ch <= '9' ) {
-    return ch-'9';
+    return ch-'0';
   } else if ( ch >= 'A' && ch <= 'Z' ) {
     return ch-'A'+10;
   } else if ( ch >= 'a' && ch <= 'z' ) {