Add functions to convert to struct time{spec|val} w/o floating point

diff --git a/include/ctype.h b/include/ctype.h
index 3f5cfad..92838eb 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -62,7 +62,7 @@
 
 __ctype_inline int isdigit(int __c)
 {
-  return __ctypes[__c+1] & __ctype_digit;
+  return ((unsigned)__c - '0') <= 9;
 }
 
 __ctype_inline int isgraph(int __c)
diff --git a/include/sys/time.h b/include/sys/time.h
index 2767a1b..6d072d7 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -15,4 +15,8 @@
 __extern int setitimer(int, const struct itimerval *, struct itimerval *);
 __extern int utimes(const char *, const struct timeval *);
 
+/* klibc-specific but useful since we don't have floating point */
+__extern char *strtotimeval(const char *str, struct timeval *tv);
+__extern char *strtotimespec(const char *str, struct timespec *tv);
+
 #endif /* _SYS_TIME_H */
diff --git a/klibc/Makefile b/klibc/Makefile
index 9e544a3..d95bbcf 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -23,7 +23,8 @@
 	  statfs.o fstatfs.o umount.o \
 	  open.o fopen.o fread.o fread2.o fgetc.o fgets.o \
 	  fwrite.o fwrite2.o fputc.o fputs.o puts.o putchar.o \
-	  sleep.o usleep.o raise.o abort.o assert.o alarm.o pause.o \
+	  sleep.o usleep.o strtotimespec.o strtotimeval.o \
+	  raise.o abort.o assert.o alarm.o pause.o \
 	  __signal.o sysv_signal.o bsd_signal.o siglist.o siglongjmp.o \
 	  sigaction.o sigpending.o sigprocmask.o sigsuspend.o \
 	  brk.o sbrk.o malloc.o realloc.o calloc.o mmap.o \
diff --git a/klibc/include/ctype.h b/klibc/include/ctype.h
index 3f5cfad..92838eb 100644
--- a/klibc/include/ctype.h
+++ b/klibc/include/ctype.h
@@ -62,7 +62,7 @@
 
 __ctype_inline int isdigit(int __c)
 {
-  return __ctypes[__c+1] & __ctype_digit;
+  return ((unsigned)__c - '0') <= 9;
 }
 
 __ctype_inline int isgraph(int __c)
diff --git a/klibc/include/sys/time.h b/klibc/include/sys/time.h
index 2767a1b..6d072d7 100644
--- a/klibc/include/sys/time.h
+++ b/klibc/include/sys/time.h
@@ -15,4 +15,8 @@
 __extern int setitimer(int, const struct itimerval *, struct itimerval *);
 __extern int utimes(const char *, const struct timeval *);
 
+/* klibc-specific but useful since we don't have floating point */
+__extern char *strtotimeval(const char *str, struct timeval *tv);
+__extern char *strtotimespec(const char *str, struct timespec *tv);
+
 #endif /* _SYS_TIME_H */
diff --git a/klibc/strtotimespec.c b/klibc/strtotimespec.c
new file mode 100644
index 0000000..9d2e7b0
--- /dev/null
+++ b/klibc/strtotimespec.c
@@ -0,0 +1,37 @@
+/*
+ * strtotimespec.c
+ *
+ * Nonstandard function which takes a string and converts it to a
+ * struct timespec.  Returns a pointer to the first non-numeric
+ * character in the string.
+ *
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+char *strtotimespec(const char *str, struct timespec *ts)
+{
+  int n;
+  char *s;
+
+  ts->tv_sec  = strtoul(str, &s, 10);
+  ts->tv_nsec = 0;
+
+  if ( *s != '.' )
+    return s;
+
+  s++;
+
+  for ( n = 0 ; n < 9 && isdigit(*s) ; n++ )
+    ts->tv_nsec = ts->tv_nsec*10 + (*s++ - '0');
+
+  while ( isdigit(*s) )
+    s++;
+  
+  for ( ; n < 9 ; n++ )
+    ts->tv_nsec *= 10;
+
+  return s;
+}
diff --git a/klibc/strtotimeval.c b/klibc/strtotimeval.c
new file mode 100644
index 0000000..7ddf1fc
--- /dev/null
+++ b/klibc/strtotimeval.c
@@ -0,0 +1,37 @@
+/*
+ * strtotimeval.c
+ *
+ * Nonstandard function which takes a string and converts it to a
+ * struct timeval.  Returns a pointer to the first non-numeric
+ * character in the string.
+ *
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+char *strtotimeval(const char *str, struct timeval *tv)
+{
+  int n;
+  char *s;
+
+  tv->tv_sec  = strtoul(str, &s, 10);
+  tv->tv_usec = 0;
+
+  if ( *s != '.' )
+    return s;
+
+  s++;
+
+  for ( n = 0 ; n < 6 && isdigit(*s) ; n++ )
+    tv->tv_usec = tv->tv_usec*10 + (*s++ - '0');
+
+  while ( isdigit(*s) )
+    s++;
+  
+  for ( ; n < 6 ; n++ )
+    tv->tv_usec *= 10;
+
+  return s;
+}