summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/posix/posix.nim283
-rwxr-xr-xlib/pure/browsers.nim43
-rwxr-xr-xlib/pure/cgi.nim86
-rwxr-xr-xlib/pure/os.nim2
-rwxr-xr-xlib/pure/sockets.nim381
-rwxr-xr-xlib/pure/strutils.nim6
-rwxr-xr-xlib/pure/times.nim2
-rwxr-xr-xlib/system.nim14
-rwxr-xr-xlib/windows/winlean.nim146
9 files changed, 719 insertions, 244 deletions
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index ddeaec664..005b6dbe0 100755
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -122,7 +122,8 @@ type
   Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} = 
     object ## Identifies the conversion from one codeset to another.
 
-  Tlconv* {.importc: "struct lconv", header: "<locale.h>", final, pure.} = object
+  Tlconv* {.importc: "struct lconv", header: "<locale.h>", final,
+            pure.} = object
     currency_symbol*: cstring
     decimal_point*: cstring
     frac_digits*: char
@@ -195,7 +196,8 @@ type
   Tpthread_mutexattr* {.importc: "pthread_mutexattr_t", 
                         header: "<sys/types.h>".} = int
   Tpthread_once* {.importc: "pthread_once_t", header: "<sys/types.h>".} = int
-  Tpthread_rwlock* {.importc: "pthread_rwlock_t", header: "<sys/types.h>".} = int
+  Tpthread_rwlock* {.importc: "pthread_rwlock_t", 
+                     header: "<sys/types.h>".} = int
   Tpthread_rwlockattr* {.importc: "pthread_rwlockattr_t", 
                          header: "<sys/types.h>".} = int
   Tpthread_spinlock* {.importc: "pthread_spinlock_t", 
@@ -310,7 +312,7 @@ type
     sigev_notify*: cint           ## Notification type. 
     sigev_signo*: cint            ## Signal number. 
     sigev_value*: Tsigval         ## Signal value. 
-    sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function. 
+    sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification func. 
     sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes.
 
   TsigVal* {.importc: "union sigval", 
@@ -368,8 +370,8 @@ type
 
   Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", 
               final, pure.} = object ## struct timeval
-    tv_sec*: ttime       ## Seconds. 
-    tv_usec*: tsuseconds ## Microseconds. 
+    tv_sec*: int       ## Seconds. 
+    tv_usec*: int ## Microseconds. 
   Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", 
              final, pure.} = object
   Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", 
@@ -595,7 +597,7 @@ var
   EAFNOSUPPORT* {.importc, header: "<errno.h>".}: cint
       ## Address family not supported.
   EAGAIN* {.importc, header: "<errno.h>".}: cint
-      ## Resource unavailable, try again (may be the same value as [EWOULDBLOCK]).
+      ## Resource unavailable, try again (may be the same value as EWOULDBLOCK).
   EALREADY* {.importc, header: "<errno.h>".}: cint
       ## Connection already in progress.
   EBADF* {.importc, header: "<errno.h>".}: cint
@@ -1061,27 +1063,42 @@ var
   X_OK* {.importc: "X_OK", header: "<unistd.h>".}: cint
 
   CS_PATH* {.importc: "_CS_PATH", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFF32_CFLAGS* {.importc: "_CS_POSIX_V6_ILP32_OFF32_CFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFF32_LDFLAGS* {.importc: "_CS_POSIX_V6_ILP32_OFF32_LDFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFF32_LIBS* {.importc: "_CS_POSIX_V6_ILP32_OFF32_LIBS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFFBIG_CFLAGS* {.importc: "_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS* {.importc: "_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_ILP32_OFFBIG_LIBS* {.importc: "_CS_POSIX_V6_ILP32_OFFBIG_LIBS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LP64_OFF64_CFLAGS* {.importc: "_CS_POSIX_V6_LP64_OFF64_CFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LP64_OFF64_LDFLAGS* {.importc: "_CS_POSIX_V6_LP64_OFF64_LDFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LP64_OFF64_LIBS* {.importc: "_CS_POSIX_V6_LP64_OFF64_LIBS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS* {.importc: "_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS* {.importc: "_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_LPBIG_OFFBIG_LIBS* {.importc: "_CS_POSIX_V6_LPBIG_OFFBIG_LIBS", header: "<unistd.h>".}: cint
-  CS_POSIX_V6_WIDTH_RESTRICTED_ENVS* {.importc: "_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFF32_CFLAGS* {.importc: "_CS_POSIX_V6_ILP32_OFF32_CFLAGS",
+    header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFF32_LDFLAGS* {.
+    importc: "_CS_POSIX_V6_ILP32_OFF32_LDFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFF32_LIBS* {.importc: "_CS_POSIX_V6_ILP32_OFF32_LIBS",
+    header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFFBIG_CFLAGS* {.
+    importc: "_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS* {.
+    importc: "_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_ILP32_OFFBIG_LIBS* {.
+    importc: "_CS_POSIX_V6_ILP32_OFFBIG_LIBS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LP64_OFF64_CFLAGS* {.
+    importc: "_CS_POSIX_V6_LP64_OFF64_CFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LP64_OFF64_LDFLAGS* {.
+    importc: "_CS_POSIX_V6_LP64_OFF64_LDFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LP64_OFF64_LIBS* {.
+    importc: "_CS_POSIX_V6_LP64_OFF64_LIBS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS* {.
+    importc: "_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS* {.
+    importc: "_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_LPBIG_OFFBIG_LIBS* {.
+    importc: "_CS_POSIX_V6_LPBIG_OFFBIG_LIBS", header: "<unistd.h>".}: cint
+  CS_POSIX_V6_WIDTH_RESTRICTED_ENVS* {.
+    importc: "_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS", header: "<unistd.h>".}: cint
   F_LOCK* {.importc: "F_LOCK", header: "<unistd.h>".}: cint
   F_TEST* {.importc: "F_TEST", header: "<unistd.h>".}: cint
   F_TLOCK* {.importc: "F_TLOCK", header: "<unistd.h>".}: cint
   F_ULOCK* {.importc: "F_ULOCK", header: "<unistd.h>".}: cint
   PC_2_SYMLINKS* {.importc: "_PC_2_SYMLINKS", header: "<unistd.h>".}: cint
-  PC_ALLOC_SIZE_MIN* {.importc: "_PC_ALLOC_SIZE_MIN", header: "<unistd.h>".}: cint
+  PC_ALLOC_SIZE_MIN* {.importc: "_PC_ALLOC_SIZE_MIN",
+    header: "<unistd.h>".}: cint
   PC_ASYNC_IO* {.importc: "_PC_ASYNC_IO", header: "<unistd.h>".}: cint
-  PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED", header: "<unistd.h>".}: cint
+  PC_CHOWN_RESTRICTED* {.importc: "_PC_CHOWN_RESTRICTED", 
+    header: "<unistd.h>".}: cint
   PC_FILESIZEBITS* {.importc: "_PC_FILESIZEBITS", header: "<unistd.h>".}: cint
   PC_LINK_MAX* {.importc: "_PC_LINK_MAX", header: "<unistd.h>".}: cint
   PC_MAX_CANON* {.importc: "_PC_MAX_CANON", header: "<unistd.h>".}: cint
@@ -1092,8 +1109,10 @@ var
   PC_PATH_MAX*{.importc: "_PC_PATH_MAX", header: "<unistd.h>".}: cint
   PC_PIPE_BUF*{.importc: "_PC_PIPE_BUF", header: "<unistd.h>".}: cint
   PC_PRIO_IO*{.importc: "_PC_PRIO_IO", header: "<unistd.h>".}: cint
-  PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE", header: "<unistd.h>".}: cint
-  PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE", header: "<unistd.h>".}: cint
+  PC_REC_INCR_XFER_SIZE*{.importc: "_PC_REC_INCR_XFER_SIZE", 
+    header: "<unistd.h>".}: cint
+  PC_REC_MIN_XFER_SIZE*{.importc: "_PC_REC_MIN_XFER_SIZE", 
+    header: "<unistd.h>".}: cint
   PC_REC_XFER_ALIGN*{.importc: "_PC_REC_XFER_ALIGN", header: "<unistd.h>".}: cint
   PC_SYMLINK_MAX*{.importc: "_PC_SYMLINK_MAX", header: "<unistd.h>".}: cint
   PC_SYNC_IO*{.importc: "_PC_SYNC_IO", header: "<unistd.h>".}: cint
@@ -1105,8 +1124,10 @@ var
   SC_2_FORT_RUN*{.importc: "_SC_2_FORT_RUN", header: "<unistd.h>".}: cint
   SC_2_LOCALEDEF*{.importc: "_SC_2_LOCALEDEF", header: "<unistd.h>".}: cint
   SC_2_PBS*{.importc: "_SC_2_PBS", header: "<unistd.h>".}: cint
-  SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING", header: "<unistd.h>".}: cint
-  SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT", header: "<unistd.h>".}: cint
+  SC_2_PBS_ACCOUNTING*{.importc: "_SC_2_PBS_ACCOUNTING", 
+    header: "<unistd.h>".}: cint
+  SC_2_PBS_CHECKPOINT*{.importc: "_SC_2_PBS_CHECKPOINT", 
+    header: "<unistd.h>".}: cint
   SC_2_PBS_LOCATE*{.importc: "_SC_2_PBS_LOCATE", header: "<unistd.h>".}: cint
   SC_2_PBS_MESSAGE*{.importc: "_SC_2_PBS_MESSAGE", header: "<unistd.h>".}: cint
   SC_2_PBS_TRACK*{.importc: "_SC_2_PBS_TRACK", header: "<unistd.h>".}: cint
@@ -1116,9 +1137,11 @@ var
   SC_ADVISORY_INFO*{.importc: "_SC_ADVISORY_INFO", header: "<unistd.h>".}: cint
   SC_AIO_LISTIO_MAX*{.importc: "_SC_AIO_LISTIO_MAX", header: "<unistd.h>".}: cint
   SC_AIO_MAX*{.importc: "_SC_AIO_MAX", header: "<unistd.h>".}: cint
-  SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX", header: "<unistd.h>".}: cint
+  SC_AIO_PRIO_DELTA_MAX*{.importc: "_SC_AIO_PRIO_DELTA_MAX", 
+    header: "<unistd.h>".}: cint
   SC_ARG_MAX*{.importc: "_SC_ARG_MAX", header: "<unistd.h>".}: cint
-  SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO", header: "<unistd.h>".}: cint
+  SC_ASYNCHRONOUS_IO*{.importc: "_SC_ASYNCHRONOUS_IO", 
+    header: "<unistd.h>".}: cint
   SC_ATEXIT_MAX*{.importc: "_SC_ATEXIT_MAX", header: "<unistd.h>".}: cint
   SC_BARRIERS*{.importc: "_SC_BARRIERS", header: "<unistd.h>".}: cint
   SC_BC_BASE_MAX*{.importc: "_SC_BC_BASE_MAX", header: "<unistd.h>".}: cint
@@ -1127,14 +1150,18 @@ var
   SC_BC_STRING_MAX*{.importc: "_SC_BC_STRING_MAX", header: "<unistd.h>".}: cint
   SC_CHILD_MAX*{.importc: "_SC_CHILD_MAX", header: "<unistd.h>".}: cint
   SC_CLK_TCK*{.importc: "_SC_CLK_TCK", header: "<unistd.h>".}: cint
-  SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION", header: "<unistd.h>".}: cint
-  SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX", header: "<unistd.h>".}: cint
+  SC_CLOCK_SELECTION*{.importc: "_SC_CLOCK_SELECTION", 
+    header: "<unistd.h>".}: cint
+  SC_COLL_WEIGHTS_MAX*{.importc: "_SC_COLL_WEIGHTS_MAX", 
+    header: "<unistd.h>".}: cint
   SC_CPUTIME*{.importc: "_SC_CPUTIME", header: "<unistd.h>".}: cint
   SC_DELAYTIMER_MAX*{.importc: "_SC_DELAYTIMER_MAX", header: "<unistd.h>".}: cint
   SC_EXPR_NEST_MAX*{.importc: "_SC_EXPR_NEST_MAX", header: "<unistd.h>".}: cint
   SC_FSYNC*{.importc: "_SC_FSYNC", header: "<unistd.h>".}: cint
-  SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX", header: "<unistd.h>".}: cint
-  SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX", header: "<unistd.h>".}: cint
+  SC_GETGR_R_SIZE_MAX*{.importc: "_SC_GETGR_R_SIZE_MAX", 
+    header: "<unistd.h>".}: cint
+  SC_GETPW_R_SIZE_MAX*{.importc: "_SC_GETPW_R_SIZE_MAX", 
+    header: "<unistd.h>".}: cint
   SC_HOST_NAME_MAX*{.importc: "_SC_HOST_NAME_MAX", header: "<unistd.h>".}: cint
   SC_IOV_MAX*{.importc: "_SC_IOV_MAX", header: "<unistd.h>".}: cint
   SC_IPV6*{.importc: "_SC_IPV6", header: "<unistd.h>".}: cint
@@ -1144,49 +1171,70 @@ var
   SC_MAPPED_FILES*{.importc: "_SC_MAPPED_FILES", header: "<unistd.h>".}: cint
   SC_MEMLOCK*{.importc: "_SC_MEMLOCK", header: "<unistd.h>".}: cint
   SC_MEMLOCK_RANGE*{.importc: "_SC_MEMLOCK_RANGE", header: "<unistd.h>".}: cint
-  SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION", header: "<unistd.h>".}: cint
-  SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING", header: "<unistd.h>".}: cint
-  SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK", header: "<unistd.h>".}: cint
+  SC_MEMORY_PROTECTION*{.importc: "_SC_MEMORY_PROTECTION", 
+    header: "<unistd.h>".}: cint
+  SC_MESSAGE_PASSING*{.importc: "_SC_MESSAGE_PASSING", 
+    header: "<unistd.h>".}: cint
+  SC_MONOTONIC_CLOCK*{.importc: "_SC_MONOTONIC_CLOCK", 
+    header: "<unistd.h>".}: cint
   SC_MQ_OPEN_MAX*{.importc: "_SC_MQ_OPEN_MAX", header: "<unistd.h>".}: cint
   SC_MQ_PRIO_MAX*{.importc: "_SC_MQ_PRIO_MAX", header: "<unistd.h>".}: cint
   SC_NGROUPS_MAX*{.importc: "_SC_NGROUPS_MAX", header: "<unistd.h>".}: cint
   SC_OPEN_MAX*{.importc: "_SC_OPEN_MAX", header: "<unistd.h>".}: cint
   SC_PAGE_SIZE*{.importc: "_SC_PAGE_SIZE", header: "<unistd.h>".}: cint
   SC_PRIORITIZED_IO*{.importc: "_SC_PRIORITIZED_IO", header: "<unistd.h>".}: cint
-  SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING", header: "<unistd.h>".}: cint
+  SC_PRIORITY_SCHEDULING*{.importc: "_SC_PRIORITY_SCHEDULING", 
+    header: "<unistd.h>".}: cint
   SC_RAW_SOCKETS*{.importc: "_SC_RAW_SOCKETS", header: "<unistd.h>".}: cint
   SC_RE_DUP_MAX*{.importc: "_SC_RE_DUP_MAX", header: "<unistd.h>".}: cint
-  SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS", header: "<unistd.h>".}: cint
-  SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS", header: "<unistd.h>".}: cint
+  SC_READER_WRITER_LOCKS*{.importc: "_SC_READER_WRITER_LOCKS", 
+    header: "<unistd.h>".}: cint
+  SC_REALTIME_SIGNALS*{.importc: "_SC_REALTIME_SIGNALS", 
+    header: "<unistd.h>".}: cint
   SC_REGEXP*{.importc: "_SC_REGEXP", header: "<unistd.h>".}: cint
   SC_RTSIG_MAX*{.importc: "_SC_RTSIG_MAX", header: "<unistd.h>".}: cint
   SC_SAVED_IDS*{.importc: "_SC_SAVED_IDS", header: "<unistd.h>".}: cint
   SC_SEM_NSEMS_MAX*{.importc: "_SC_SEM_NSEMS_MAX", header: "<unistd.h>".}: cint
   SC_SEM_VALUE_MAX*{.importc: "_SC_SEM_VALUE_MAX", header: "<unistd.h>".}: cint
   SC_SEMAPHORES*{.importc: "_SC_SEMAPHORES", header: "<unistd.h>".}: cint
-  SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS", header: "<unistd.h>".}: cint
+  SC_SHARED_MEMORY_OBJECTS*{.importc: "_SC_SHARED_MEMORY_OBJECTS", 
+    header: "<unistd.h>".}: cint
   SC_SHELL*{.importc: "_SC_SHELL", header: "<unistd.h>".}: cint
   SC_SIGQUEUE_MAX*{.importc: "_SC_SIGQUEUE_MAX", header: "<unistd.h>".}: cint
   SC_SPAWN*{.importc: "_SC_SPAWN", header: "<unistd.h>".}: cint
   SC_SPIN_LOCKS*{.importc: "_SC_SPIN_LOCKS", header: "<unistd.h>".}: cint
-  SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER", header: "<unistd.h>".}: cint
+  SC_SPORADIC_SERVER*{.importc: "_SC_SPORADIC_SERVER", 
+    header: "<unistd.h>".}: cint
   SC_SS_REPL_MAX*{.importc: "_SC_SS_REPL_MAX", header: "<unistd.h>".}: cint
   SC_STREAM_MAX*{.importc: "_SC_STREAM_MAX", header: "<unistd.h>".}: cint
   SC_SYMLOOP_MAX*{.importc: "_SC_SYMLOOP_MAX", header: "<unistd.h>".}: cint
-  SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO", header: "<unistd.h>".}: cint
-  SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR", header: "<unistd.h>".}: cint
-  SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE", header: "<unistd.h>".}: cint
+  SC_SYNCHRONIZED_IO*{.importc: "_SC_SYNCHRONIZED_IO", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_ATTR_STACKADDR*{.importc: "_SC_THREAD_ATTR_STACKADDR", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_ATTR_STACKSIZE*{.importc: "_SC_THREAD_ATTR_STACKSIZE", 
+    header: "<unistd.h>".}: cint
   SC_THREAD_CPUTIME*{.importc: "_SC_THREAD_CPUTIME", header: "<unistd.h>".}: cint
-  SC_THREAD_DESTRUCTOR_ITERATIONS*{.importc: "_SC_THREAD_DESTRUCTOR_ITERATIONS", header: "<unistd.h>".}: cint
-  SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX", header: "<unistd.h>".}: cint
-  SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT", header: "<unistd.h>".}: cint
-  SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT", header: "<unistd.h>".}: cint
-  SC_THREAD_PRIORITY_SCHEDULING*{.importc: "_SC_THREAD_PRIORITY_SCHEDULING", header: "<unistd.h>".}: cint
-  SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED", header: "<unistd.h>".}: cint
-  SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS", header: "<unistd.h>".}: cint
-  SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER", header: "<unistd.h>".}: cint
-  SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN", header: "<unistd.h>".}: cint
-  SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX", header: "<unistd.h>".}: cint
+  SC_THREAD_DESTRUCTOR_ITERATIONS*{.importc: "_SC_THREAD_DESTRUCTOR_ITERATIONS",
+    header: "<unistd.h>".}: cint
+  SC_THREAD_KEYS_MAX*{.importc: "_SC_THREAD_KEYS_MAX", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_PRIO_INHERIT*{.importc: "_SC_THREAD_PRIO_INHERIT", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_PRIO_PROTECT*{.importc: "_SC_THREAD_PRIO_PROTECT", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_PRIORITY_SCHEDULING*{.importc: "_SC_THREAD_PRIORITY_SCHEDULING",
+    header: "<unistd.h>".}: cint
+  SC_THREAD_PROCESS_SHARED*{.importc: "_SC_THREAD_PROCESS_SHARED", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_SAFE_FUNCTIONS*{.importc: "_SC_THREAD_SAFE_FUNCTIONS", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_SPORADIC_SERVER*{.importc: "_SC_THREAD_SPORADIC_SERVER", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_STACK_MIN*{.importc: "_SC_THREAD_STACK_MIN", 
+    header: "<unistd.h>".}: cint
+  SC_THREAD_THREADS_MAX*{.importc: "_SC_THREAD_THREADS_MAX", 
+    header: "<unistd.h>".}: cint
   SC_THREADS*{.importc: "_SC_THREADS", header: "<unistd.h>".}: cint
   SC_TIMEOUTS*{.importc: "_SC_TIMEOUTS", header: "<unistd.h>".}: cint
   SC_TIMER_MAX*{.importc: "_SC_TIMER_MAX", header: "<unistd.h>".}: cint
@@ -1372,7 +1420,8 @@ var
   WEXITED* {.importc, header: "<sys/wait.h>".}: cint
     ## Wait for processes that have exited.
   WSTOPPED* {.importc, header: "<sys/wait.h>".}: cint
-    ## Status is returned for any child that has stopped upon receipt of a signal.
+    ## Status is returned for any child that has stopped upon receipt 
+    ## of a signal.
   WCONTINUED* {.importc, header: "<sys/wait.h>".}: cint
     ## Status is returned for any child that was stopped and has been continued.
   WNOWAIT* {.importc, header: "<sys/wait.h>".}: cint
@@ -1385,7 +1434,8 @@ var
     ## Request for default signal handling.
   SIG_ERR* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Return value from signal() in case of error.
-  cSIG_HOLD* {.importc: "SIG_HOLD", header: "<signal.h>".}: proc (x: cint) {.noconv.}
+  cSIG_HOLD* {.importc: "SIG_HOLD", 
+    header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Request that signal be held.
   SIG_IGN* {.importc, header: "<signal.h>".}: proc (x: cint) {.noconv.}
     ## Request that signal be ignored. 
@@ -1685,8 +1735,10 @@ proc ntohs*(a1: int16): int16 {.importc, header: "<arpa/inet.h>".}
 
 proc inet_addr*(a1: cstring): int32 {.importc, header: "<arpa/inet.h>".}
 proc inet_ntoa*(a1: int32): cstring {.importc, header: "<arpa/inet.h>".}
-proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.importc, header: "<arpa/inet.h>".}
-proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.importc, header: "<arpa/inet.h>".}
+proc inet_ntop*(a1: cint, a2: pointer, a3: cstring, a4: int32): cstring {.
+  importc, header: "<arpa/inet.h>".}
+proc inet_pton*(a1: cint, a2: cstring, a3: pointer): cint {.
+  importc, header: "<arpa/inet.h>".}
 
 var
   in6addr_any* {.importc, header: "<netinet/in.h>".}: TIn6Addr
@@ -1714,13 +1766,17 @@ proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>".}
 proc creat*(a1: cstring, a2: Tmode): cint {.importc, header: "<fcntl.h>".}
 proc fcntl*(a1: cint, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
 proc open*(a1: cstring, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
-proc posix_fadvise*(a1: cint, a2, a3: Toff, a4: cint): cint {.importc, header: "<fcntl.h>".}
-proc posix_fallocate*(a1: cint, a2, a3: Toff): cint {.importc, header: "<fcntl.h>".}
+proc posix_fadvise*(a1: cint, a2, a3: Toff, a4: cint): cint {.
+  importc, header: "<fcntl.h>".}
+proc posix_fallocate*(a1: cint, a2, a3: Toff): cint {.
+  importc, header: "<fcntl.h>".}
 
 proc feclearexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fegetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.importc, header: "<fenv.h>".}
+proc fegetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
+  importc, header: "<fenv.h>".}
 proc feraiseexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
-proc fesetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.importc, header: "<fenv.h>".}
+proc fesetexceptflag*(a1: ptr Tfexcept, a2: cint): cint {.
+  importc, header: "<fenv.h>".}
 proc fetestexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
 proc fegetround*(): cint {.importc, header: "<fenv.h>".}
 proc fesetround*(a1: cint): cint {.importc, header: "<fenv.h>".}
@@ -1737,7 +1793,8 @@ proc ftw*(a1: cstring,
          a2: proc (x1: cstring, x2: ptr TStat, x3: cint): cint {.noconv.},
          a3: cint): cint {.importc, header: "<ftw.h>".}
 proc nftw*(a1: cstring, 
-          a2: proc (x1: cstring, x2: ptr TStat, x3: cint, x4: ptr TFTW): cint {.noconv.},
+          a2: proc (x1: cstring, x2: ptr TStat, 
+                    x3: cint, x4: ptr TFTW): cint {.noconv.},
           a3: cint,
           a4: cint): cint {.importc, header: "<ftw.h>".}
 
@@ -1751,7 +1808,8 @@ proc getgrnam*(a1: cstring): ptr TGroup {.importc, header: "<grp.h>".}
 proc getgrgid_r*(a1: Tgid, a2: ptr TGroup, a3: cstring, a4: int,
                  a5: ptr ptr TGroup): cint {.importc, header: "<grp.h>".}
 proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring, 
-                  a4: int, a5: ptr ptr TGroup): cint {.importc, header: "<grp.h>".}
+                  a4: int, a5: ptr ptr TGroup): cint {.
+                 importc, header: "<grp.h>".}
 proc getgrent*(): ptr TGroup {.importc, header: "<grp.h>".}
 proc endgrent*() {.importc, header: "<grp.h>".}
 proc setgrent*() {.importc, header: "<grp.h>".}
@@ -1775,12 +1833,18 @@ proc strfmon*(a1: cstring, a2: int, a3: cstring): int {.varargs,
    importc, header: "<monetary.h>".}
 
 proc mq_close*(a1: Tmqd): cint {.importc, header: "<mqueue.h>".}
-proc mq_getattr*(a1: Tmqd, a2: ptr Tmq_attr): cint {.importc, header: "<mqueue.h>".}
-proc mq_notify*(a1: Tmqd, a2: ptr Tsigevent): cint {.importc, header: "<mqueue.h>".}
-proc mq_open*(a1: cstring, a2: cint): TMqd {.varargs, importc, header: "<mqueue.h>".}
-proc mq_receive*(a1: Tmqd, a2: cstring, a3: int, a4: var int): int {.importc, header: "<mqueue.h>".}
-proc mq_send*(a1: Tmqd, a2: cstring, a3: int, a4: int): cint {.importc, header: "<mqueue.h>".}
-proc mq_setattr*(a1: Tmqd, a2, a3: ptr Tmq_attr): cint {.importc, header: "<mqueue.h>".}
+proc mq_getattr*(a1: Tmqd, a2: ptr Tmq_attr): cint {.
+  importc, header: "<mqueue.h>".}
+proc mq_notify*(a1: Tmqd, a2: ptr Tsigevent): cint {.
+  importc, header: "<mqueue.h>".}
+proc mq_open*(a1: cstring, a2: cint): TMqd {.
+  varargs, importc, header: "<mqueue.h>".}
+proc mq_receive*(a1: Tmqd, a2: cstring, a3: int, a4: var int): int {.
+  importc, header: "<mqueue.h>".}
+proc mq_send*(a1: Tmqd, a2: cstring, a3: int, a4: int): cint {.
+  importc, header: "<mqueue.h>".}
+proc mq_setattr*(a1: Tmqd, a2, a3: ptr Tmq_attr): cint {.
+  importc, header: "<mqueue.h>".}
 
 proc mq_timedreceive*(a1: Tmqd, a2: cstring, a3: int, a4: int, 
                       a5: ptr TTimespec): int {.importc, header: "<mqueue.h>".}
@@ -1801,10 +1865,14 @@ proc setpwent*() {.importc, header: "<pwd.h>".}
 
 proc uname*(a1: var Tutsname): cint {.importc, header: "<sys/utsname.h>".}
 
-proc pthread_atfork*(a1, a2, a3: proc {.noconv.}): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_destroy*(a1: ptr Tpthread_attr): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_getdetachstate*(a1: ptr Tpthread_attr, a2: cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_getguardsize*(a1: ptr Tpthread_attr, a2: var cint): cint {.importc, header: "<pthread.h>".}
+proc pthread_atfork*(a1, a2, a3: proc {.noconv.}): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_destroy*(a1: ptr Tpthread_attr): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_getdetachstate*(a1: ptr Tpthread_attr, a2: cint): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_getguardsize*(a1: ptr Tpthread_attr, a2: var cint): cint {.
+  importc, header: "<pthread.h>".}
 proc pthread_attr_getinheritsched*(a1: ptr Tpthread_attr,
           a2: var cint): cint {.importc, header: "<pthread.h>".}
 proc pthread_attr_getschedparam*(a1: ptr Tpthread_attr,
@@ -1819,30 +1887,48 @@ proc pthread_attr_getstackaddr*(a1: ptr Tpthread_attr,
           a2: var pointer): cint {.importc, header: "<pthread.h>".}
 proc pthread_attr_getstacksize*(a1: ptr Tpthread_attr,
           a2: var int): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_init*(a1: ptr Tpthread_attr): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setdetachstate*(a1: ptr Tpthread_attr, a2: cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setguardsize*(a1: ptr Tpthread_attr, a2: int): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setinheritsched*(a1: ptr Tpthread_attr, a2: cint): cint {.importc, header: "<pthread.h>".}
+proc pthread_attr_init*(a1: ptr Tpthread_attr): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setdetachstate*(a1: ptr Tpthread_attr, a2: cint): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setguardsize*(a1: ptr Tpthread_attr, a2: int): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setinheritsched*(a1: ptr Tpthread_attr, a2: cint): cint {.
+  importc, header: "<pthread.h>".}
 proc pthread_attr_setschedparam*(a1: ptr Tpthread_attr,
           a2: ptr Tsched_param): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setschedpolicy*(a1: ptr Tpthread_attr, a2: cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setscope*(a1: ptr Tpthread_attr, a2: cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setstack*(a1: ptr Tpthread_attr, a2: pointer, a3: int): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setstackaddr*(a1: ptr TPthread_attr, a2: pointer): cint {.importc, header: "<pthread.h>".}
-proc pthread_attr_setstacksize*(a1: ptr TPthread_attr, a2: int): cint {.importc, header: "<pthread.h>".}
-proc pthread_barrier_destroy*(a1: ptr Tpthread_barrier): cint {.importc, header: "<pthread.h>".}
+proc pthread_attr_setschedpolicy*(a1: ptr Tpthread_attr, a2: cint): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setscope*(a1: ptr Tpthread_attr, a2: cint): cint {.importc,
+  header: "<pthread.h>".}
+proc pthread_attr_setstack*(a1: ptr Tpthread_attr, a2: pointer, a3: int): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setstackaddr*(a1: ptr TPthread_attr, a2: pointer): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_attr_setstacksize*(a1: ptr TPthread_attr, a2: int): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_barrier_destroy*(a1: ptr Tpthread_barrier): cint {.
+  importc, header: "<pthread.h>".}
 proc pthread_barrier_init*(a1: ptr Tpthread_barrier,
-         a2: ptr Tpthread_barrierattr, a3: cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_barrier_wait*(a1: ptr Tpthread_barrier): cint {.importc, header: "<pthread.h>".}
-proc pthread_barrierattr_destroy*(a1: ptr Tpthread_barrierattr): cint {.importc, header: "<pthread.h>".}
+         a2: ptr Tpthread_barrierattr, a3: cint): cint {.
+         importc, header: "<pthread.h>".}
+proc pthread_barrier_wait*(a1: ptr Tpthread_barrier): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_barrierattr_destroy*(a1: ptr Tpthread_barrierattr): cint {.
+  importc, header: "<pthread.h>".}
 proc pthread_barrierattr_getpshared*(
-          a1: ptr Tpthread_barrierattr, a2: var cint): cint {.importc, header: "<pthread.h>".}
-proc pthread_barrierattr_init*(a1: ptr TPthread_barrierattr): cint {.importc, header: "<pthread.h>".}
-proc pthread_barrierattr_setpshared*(a1: ptr TPthread_barrierattr, a2: cint): cint {.importc, header: "<pthread.h>".}
+          a1: ptr Tpthread_barrierattr, a2: var cint): cint {.
+          importc, header: "<pthread.h>".}
+proc pthread_barrierattr_init*(a1: ptr TPthread_barrierattr): cint {.
+  importc, header: "<pthread.h>".}
+proc pthread_barrierattr_setpshared*(a1: ptr TPthread_barrierattr, 
+  a2: cint): cint {.importc, header: "<pthread.h>".}
 proc pthread_cancel*(a1: Tpthread): cint {.importc, header: "<pthread.h>".}
-proc pthread_cleanup_push*(a1: proc (x: pointer) {.noconv.}, a2: pointer) {.importc, header: "<pthread.h>".}
+proc pthread_cleanup_push*(a1: proc (x: pointer) {.noconv.}, a2: pointer) {.
+  importc, header: "<pthread.h>".}
 proc pthread_cleanup_pop*(a1: cint) {.importc, header: "<pthread.h>".}
-proc pthread_cond_broadcast*(a1: ptr Tpthread_cond): cint {.importc, header: "<pthread.h>".}
+proc pthread_cond_broadcast*(a1: ptr Tpthread_cond): cint {.
+  importc, header: "<pthread.h>".}
 proc pthread_cond_destroy*(a1: ptr Tpthread_cond): cint {.importc, header: "<pthread.h>".}
 proc pthread_cond_init*(a1: ptr Tpthread_cond,
           a2: ptr Tpthread_condattr): cint {.importc, header: "<pthread.h>".}
@@ -2167,7 +2253,7 @@ proc tzset*() {.importc, header: "<time.h>".}
 proc wait*(a1: var cint): tpid {.importc, header: "<sys/wait.h>".}
 proc waitid*(a1: cint, a2: tid, a3: var Tsiginfo, a4: cint): cint {.
   importc, header: "<sys/wait.h>".}
-proc waitpid*(a1: tpid, a2: var cint, a3: cint): tpid  {.
+proc waitpid*(a1: tpid, a2: var cint, a3: cint): tpid {.
   importc, header: "<sys/wait.h>".}
 
 proc bsd_signal*(a1: cint, a2: proc (x: pointer) {.noconv.}) {.
@@ -2198,11 +2284,13 @@ proc sigprocmask*(a1: cint, a2, a3: var tsigset): cint {.
 proc sigqueue*(a1: tpid, a2: cint, a3: Tsigval): cint {.
   importc, header: "<signal.h>".}
 proc sigrelse*(a1: cint): cint {.importc, header: "<signal.h>".}
-proc sigset*(a1: int, a2: proc (x: cint) {.noconv.}) {.importc, header: "<signal.h>".}
+proc sigset*(a1: int, a2: proc (x: cint) {.noconv.}) {.
+  importc, header: "<signal.h>".}
 proc sigsuspend*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
 proc sigtimedwait*(a1: var Tsigset, a2: var tsiginfo, 
                    a3: var ttimespec): cint {.importc, header: "<signal.h>".}
-proc sigwait*(a1: var Tsigset, a2: var cint): cint {.importc, header: "<signal.h>".}
+proc sigwait*(a1: var Tsigset, a2: var cint): cint {.
+  importc, header: "<signal.h>".}
 proc sigwaitinfo*(a1: var Tsigset, a2: var tsiginfo): cint {.
   importc, header: "<signal.h>".}
 
@@ -2210,7 +2298,8 @@ proc sigwaitinfo*(a1: var Tsigset, a2: var tsiginfo): cint {.
 proc catclose*(a1: Tnl_catd): cint {.importc, header: "<nl_types.h>".}
 proc catgets*(a1: Tnl_catd, a2, a3: cint, a4: cstring): cstring {.
   importc, header: "<nl_types.h>".}
-proc catopen*(a1: cstring, a2: cint): Tnl_catd {.importc, header: "<nl_types.h>".}
+proc catopen*(a1: cstring, a2: cint): Tnl_catd {.
+  importc, header: "<nl_types.h>".}
 
 proc sched_get_priority_max*(a1: cint): cint {.importc, header: "<sched.h>".}
 proc sched_get_priority_min*(a1: cint): cint {.importc, header: "<sched.h>".}
@@ -2233,9 +2322,9 @@ proc FD_ISSET*(a1: cint, a2: var Tfd_set): cint {.
 proc FD_SET*(a1: cint, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
 proc FD_ZERO*(a1: var Tfd_set) {.importc, header: "<sys/select.h>".}
 
-proc pselect*(a1: cint, a2, a3, a4: var Tfd_set, a5: var ttimespec,
+proc pselect*(a1: cint, a2, a3, a4: ptr Tfd_set, a5: ptr ttimespec,
          a6: var Tsigset): cint  {.importc, header: "<sys/select.h>".}
-proc select*(a1: cint, a2, a3, a4: var Tfd_set, a5: var ttimeval): cint {.
+proc select*(a1: cint, a2, a3, a4: ptr Tfd_set, a5: ptr ttimeval): cint {.
              importc, header: "<sys/select.h>".}
 
 when hasSpawnH:
diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim
new file mode 100755
index 000000000..243c07dad
--- /dev/null
+++ b/lib/pure/browsers.nim
@@ -0,0 +1,43 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2010 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a simple proc for opening URLs with the user's
+## default browser.
+
+import strutils
+
+when defined(windows):
+  import winlean
+else:
+  import os, osproc
+
+proc openDefaultBrowser*(url: string) =
+  ## opens `url` with the user's default browser. This does not block.
+  ##
+  ## Under Windows, ``ShellExecute`` is used. Under Mac OS X the ``open``
+  ## command is used. Under Unix, it is checked if ``gnome-open`` exists and
+  ## used if it does. Next attempt is ``kde-open``, then ``xdg-open``.
+  ## Otherwise the environment variable ``BROWSER`` is used to determine the
+  ## default browser to use.
+  when defined(windows):
+    discard ShellExecute(0'i32, "open", url, nil, nil, SW_SHOWNORMAL)
+  elif defined(macosx):
+    discard execShellCmd("open " & quoteIfContainsWhite(url))
+  else:
+    const attempts = ["gnome-open ", "kde-open ", "xdg-open "]
+    var u = quoteIfContainsWhite(url)
+    for a in items(attempts):
+      if execShellCmd(a & u) == 0: return
+    for b in getEnv("BROWSER").split(PathSep):
+      try:
+        # we use ``startProcess`` here because we don't want to block!
+        discard startProcess(command=b, args=[url], options={poUseShell})
+        return
+      except EOS:
+        nil
diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim
index 93d29189b..210af00fc 100755
--- a/lib/pure/cgi.nim
+++ b/lib/pure/cgi.nim
@@ -120,51 +120,57 @@ proc getEncodedData(allowedMethods: set[TRequestMethod]): string =
     if methodNone notin allowedMethods:
       cgiError("'REQUEST_METHOD' must be 'POST' or 'GET'")
 
+iterator decodeData*(data: string): tuple[key, value: string] = 
+  ## Reads and decodes CGI data and yields the (name, value) pairs the
+  ## data consists of.
+  var i = 0
+  var name = ""
+  var value = ""
+  # decode everything in one pass:
+  while data[i] != '\0':
+    setLen(name, 0) # reuse memory
+    while true:
+      case data[i]
+      of '\0': break
+      of '%': 
+        var x = 0
+        handleHexChar(data[i+1], x)
+        handleHexChar(data[i+2], x)
+        inc(i, 2)
+        add(name, chr(x))
+      of '+': add(name, ' ')
+      of '=', '&': break
+      else: add(name, data[i])
+      inc(i)
+    if data[i] != '=': cgiError("'=' expected")
+    inc(i) # skip '='
+    setLen(value, 0) # reuse memory
+    while true:
+      case data[i]
+      of '%': 
+        var x = 0
+        handleHexChar(data[i+1], x)
+        handleHexChar(data[i+2], x)
+        inc(i, 2)
+        add(value, chr(x))
+      of '+': add(value, ' ')
+      of '&', '\0': break
+      else: add(value, data[i])
+      inc(i)
+    yield (name, value)
+    if data[i] == '&': inc(i)
+    elif data[i] == '\0': break
+    else: cgiError("'&' expected")
+ 
 iterator decodeData*(allowedMethods: set[TRequestMethod] = 
        {methodNone, methodPost, methodGet}): tuple[key, value: string] = 
   ## Reads and decodes CGI data and yields the (name, value) pairs the
   ## data consists of. If the client does not use a method listed in the
   ## `allowedMethods` set, an `ECgi` exception is raised.
-  var enc = getEncodedData(allowedMethods)
-  if not isNil(enc): 
-    # decode everything in one pass:
-    var i = 0
-    var name = ""
-    var value = ""
-    while enc[i] != '\0':
-      setLen(name, 0) # reuse memory
-      while true:
-        case enc[i]
-        of '\0': break
-        of '%': 
-          var x = 0
-          handleHexChar(enc[i+1], x)
-          handleHexChar(enc[i+2], x)
-          inc(i, 2)
-          add(name, chr(x))
-        of '+': add(name, ' ')
-        of '=', '&': break
-        else: add(name, enc[i])
-        inc(i)
-      if enc[i] != '=': cgiError("'=' expected")
-      inc(i) # skip '='
-      setLen(value, 0) # reuse memory
-      while true:
-        case enc[i]
-        of '%': 
-          var x = 0
-          handleHexChar(enc[i+1], x)
-          handleHexChar(enc[i+2], x)
-          inc(i, 2)
-          add(value, chr(x))
-        of '+': add(value, ' ')
-        of '&', '\0': break
-        else: add(value, enc[i])
-        inc(i)
-      yield (name, value)
-      if enc[i] == '&': inc(i)
-      elif enc[i] == '\0': break
-      else: cgiError("'&' expected")
+  var data = getEncodedData(allowedMethods)
+  if not isNil(data): 
+    for key, value in decodeData(data):
+      yield key, value
 
 proc readData*(allowedMethods: set[TRequestMethod] = 
                {methodNone, methodPost, methodGet}): PStringTable = 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 85ac9c83c..1bbe55bb9 100755
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -577,7 +577,7 @@ proc cmpPaths*(pathA, pathB: string): int {.noSideEffect.} =
 proc sameFile*(path1, path2: string): bool =
   ## Returns True if both pathname arguments refer to the same file or
   ## directory (as indicated by device number and i-node number).
-  ## Raises an exception if an os.stat() call on either pathname fails.
+  ## Raises an exception if an stat() call on either pathname fails.
   when defined(Windows):
     var
       a, b: TWin32FindData
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index be2e4434a..9419b82b9 100755
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -7,26 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements a simple portable type-safe sockets layer. **Note**:
-## This module is incomplete and probably buggy. It does not work on Windows
-## yet. Help if you are interested.
-
-# TODO:
-# getservbyname(name, proto)
-# getservbyport(port, proto)
-# gethostbyname(name)
-# gethostbyaddr(addr)
-# shutdown(sock, how)
-# connect(sock, address, port)
-# select({ socket, ... }, timeout)
-
-# sendto
-# recvfrom
-
-# bind(socket, address, port)
-
-# getsockopt(socket, level, optname)
-# setsockopt(socket, level, optname, value)
+## This module implements a simple portable type-safe sockets layer.
 
 import os
 
@@ -35,6 +16,8 @@ when defined(Windows):
 else:
   import posix
 
+# Note: The enumerations are mapped to Window's constants.
+
 type
   TSocket* = distinct cint ## socket type
   TPort* = distinct int16  ## port type
@@ -42,87 +25,149 @@ type
   TDomain* = enum   ## domain, which specifies the protocol family of the
                     ## created socket. Other domains than those that are listed
                     ## here are unsupported.
-    AF_UNIX,        ## for local socket (using a file).
-    AF_INET,        ## for network protocol IPv4 or
-    AF_INET6        ## for network protocol IPv6.
-
-  TType* = enum     ## second argument to `socket` proc
-    SOCK_STREAM,    ## reliable stream-oriented service or Stream Sockets
-    SOCK_DGRAM,     ## datagram service or Datagram Sockets
-    SOCK_SEQPACKET, ## reliable sequenced packet service, or
-    SOCK_RAW        ## raw protocols atop the network layer.
-
-  TProtocol* = enum ## third argument to `socket` proc
-    IPPROTO_TCP,    ## Transmission control protocol. 
-    IPPROTO_UDP,    ## User datagram protocol.
-    IPPROTO_IP,     ## Internet protocol. 
-    IPPROTO_IPV6,   ## Internet Protocol Version 6. 
-    IPPROTO_RAW,    ## Raw IP Packets Protocol. 
-    IPPROTO_ICMP    ## Control message protocol. 
+    AF_UNIX,        ## for local socket (using a file). Unsupported on Windows.
+    AF_INET = 2,    ## for network protocol IPv4 or
+    AF_INET6 = 23   ## for network protocol IPv6.
+
+  TType* = enum        ## second argument to `socket` proc
+    SOCK_STREAM = 1,   ## reliable stream-oriented service or Stream Sockets
+    SOCK_DGRAM = 2,    ## datagram service or Datagram Sockets
+    SOCK_RAW = 3,      ## raw protocols atop the network layer.
+    SOCK_SEQPACKET = 5 ## reliable sequenced packet service, or
+
+  TProtocol* = enum     ## third argument to `socket` proc
+    IPPROTO_TCP = 6,    ## Transmission control protocol. 
+    IPPROTO_UDP = 17,   ## User datagram protocol.
+    IPPROTO_IP,         ## Internet protocol. Unsupported on Windows.
+    IPPROTO_IPV6,       ## Internet Protocol Version 6. Unsupported on Windows.
+    IPPROTO_RAW,        ## Raw IP Packets Protocol. Unsupported on Windows.
+    IPPROTO_ICMP        ## Control message protocol. Unsupported on Windows.
+
+  TServent* {.pure, final.} = object ## information about a service
+    name*: string
+    aliases*: seq[string]
+    port*: TPort
+    proto*: string
+
+  Thostent* {.pure, final.} = object ## information about a given host
+    name*: string
+    aliases*: seq[string]
+    addrtype*: TDomain
+    length*: int
+    addrList*: seq[string]
 
 const
   InvalidSocket* = TSocket(-1'i32) ## invalid socket number
 
 proc `==`*(a, b: TSocket): bool {.borrow.}
+  ## ``==`` for sockets. 
+
 proc `==`*(a, b: TPort): bool {.borrow.}
+  ## ``==`` for ports.
 
-proc `$`* (p: TPort): string = result = $ze(int16(p))
-
-proc ToInt(domain: TDomain): cint =
-  case domain
-  of AF_UNIX:        result = posix.AF_UNIX
-  of AF_INET:        result = posix.AF_INET
-  of AF_INET6:       result = posix.AF_INET6
-
-proc ToInt(typ: TType): cint =
-  case typ
-  of SOCK_STREAM:    result = posix.SOCK_STREAM
-  of SOCK_DGRAM:     result = posix.SOCK_DGRAM
-  of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
-  of SOCK_RAW:       result = posix.SOCK_RAW
-
-proc ToInt(p: TProtocol): cint =
-  case p
-  of IPPROTO_TCP:    result = posix.IPPROTO_TCP
-  of IPPROTO_UDP:    result = posix.IPPROTO_UDP
-  of IPPROTO_IP:     result = posix.IPPROTO_IP
-  of IPPROTO_IPV6:   result = posix.IPPROTO_IPV6
-  of IPPROTO_RAW:    result = posix.IPPROTO_RAW
-  of IPPROTO_ICMP:   result = posix.IPPROTO_ICMP
-
-proc socket*(domain: TDomain = AF_INET6, typ: TType = SOCK_STREAM,
+proc `$`*(p: TPort): string = 
+  ## returns the port number as a string
+  result = $ze(int16(p))
+
+proc ntohl*(x: int32): int32 = 
+  ## Converts 32-bit integers from network to host byte order.
+  ## On machines where the host byte order is the same as network byte order,
+  ## this is a no-op; otherwise, it performs a 4-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 24'i32) or
+                 (x shr 8'i32 and 0xff00'i32) or
+                 (x shl 8'i32 and 0xff0000'i32) or
+                 (x shl 24'i32)
+
+proc ntohs*(x: int16): int16 =
+  ## Converts 16-bit integers from network to host byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 2-byte swap operation.
+  when cpuEndian == bigEndian: result = x
+  else: result = (x shr 8'i16) or (x shl 8'i16)
+
+proc htonl*(x: int32): int32 =
+  ## Converts 32-bit integers from host to network byte order. On machines
+  ## where the host byte order is the same as network byte order, this is
+  ## a no-op; otherwise, it performs a 4-byte swap operation.
+  result = sockets.ntohl(x)
+
+proc htons*(x: int16): int16 =
+  ## Converts 16-bit positive integers from host to network byte order.
+  ## On machines where the host byte order is the same as network byte
+  ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
+  result = sockets.ntohs(x)
+  
+when defined(Posix):
+  proc ToInt(domain: TDomain): cint =
+    case domain
+    of AF_UNIX:        result = posix.AF_UNIX
+    of AF_INET:        result = posix.AF_INET
+    of AF_INET6:       result = posix.AF_INET6
+    else: nil
+
+  proc ToInt(typ: TType): cint =
+    case typ
+    of SOCK_STREAM:    result = posix.SOCK_STREAM
+    of SOCK_DGRAM:     result = posix.SOCK_DGRAM
+    of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
+    of SOCK_RAW:       result = posix.SOCK_RAW
+    else: nil
+
+  proc ToInt(p: TProtocol): cint =
+    case p
+    of IPPROTO_TCP:    result = posix.IPPROTO_TCP
+    of IPPROTO_UDP:    result = posix.IPPROTO_UDP
+    of IPPROTO_IP:     result = posix.IPPROTO_IP
+    of IPPROTO_IPV6:   result = posix.IPPROTO_IPV6
+    of IPPROTO_RAW:    result = posix.IPPROTO_RAW
+    of IPPROTO_ICMP:   result = posix.IPPROTO_ICMP
+    else: nil
+
+proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
              protocol: TProtocol = IPPROTO_TCP): TSocket =
   ## creates a new socket; returns `InvalidSocket` if an error occurs.  
-  result = TSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)))
+  when defined(Windows):
+    result = TSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)))
+  else:
+    result = TSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)))
 
 proc listen*(socket: TSocket, attempts = 5) =
   ## listens to socket.
-  if posix.listen(cint(socket), cint(attempts)) < 0'i32: OSError()
+  if listen(cint(socket), cint(attempts)) < 0'i32: OSError()
 
 proc bindAddr*(socket: TSocket, port = TPort(0)) =
+  ## binds a port number to a socket.
   var name: Tsockaddr_in
-  name.sin_family = posix.AF_INET
-  name.sin_port = htons(int16(port))
-  name.sin_addr.s_addr = htonl(INADDR_ANY)
+  when defined(Windows):
+    name.sin_family = int16(ord(AF_INET))
+  else:
+    name.sin_family = posix.AF_INET
+  name.sin_port = sockets.htons(int16(port))
+  name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
   if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)),
                 sizeof(name)) < 0'i32:
     OSError()
   
 proc getSockName*(socket: TSocket): TPort = 
+  ## returns the socket's associated port number.
   var name: Tsockaddr_in
-  name.sin_family = posix.AF_INET
+  when defined(Windows):
+    name.sin_family = int16(ord(AF_INET))
+  else:
+    name.sin_family = posix.AF_INET
   #name.sin_port = htons(cint16(port))
   #name.sin_addr.s_addr = htonl(INADDR_ANY)
   var namelen: cint = sizeof(name)
   if getsockname(cint(socket), cast[ptr TSockAddr](addr(name)),
                  addr(namelen)) == -1'i32:
     OSError()
-  result = TPort(ntohs(name.sin_port))
+  result = TPort(sockets.ntohs(name.sin_port))
 
 proc accept*(server: TSocket): TSocket =
   ## waits for a client and returns its socket
   var client: Tsockaddr_in
-  var clientLen: TsockLen = sizeof(client)
+  var clientLen: cint = sizeof(client)
   result = TSocket(accept(cint(server), cast[ptr TSockAddr](addr(client)),
                           addr(clientLen)))
 
@@ -133,8 +178,163 @@ proc close*(socket: TSocket) =
   else:
     discard posix.close(cint(socket))
 
+proc getServByName*(name, proto: string): TServent =
+  ## well-known getservbyname proc.
+  when defined(Windows):
+    var s = winlean.getservbyname(name, proto)
+  else:
+    var s = posix.getservbyname(name, proto)
+  if s == nil: OSError()
+  result.name = $s.s_name
+  result.aliases = cstringArrayToSeq(s.s_aliases)
+  result.port = TPort(s.s_port)
+  result.proto = $s.s_proto
+  
+proc getServByPort*(port: TPort, proto: string): TServent = 
+  ## well-known getservbyport proc.
+  when defined(Windows):
+    var s = winlean.getservbyport(ze(int16(port)), proto)
+  else:
+    var s = posix.getservbyport(ze(int16(port)), proto)
+  if s == nil: OSError()
+  result.name = $s.s_name
+  result.aliases = cstringArrayToSeq(s.s_aliases)
+  result.port = TPort(s.s_port)
+  result.proto = $s.s_proto
+
+proc getHostByName*(name: string): THostEnt = 
+  ## well-known gethostbyname proc.
+  when defined(Windows):
+    var s = winlean.gethostbyname(name)
+  else:
+    var s = posix.gethostbyname(name)
+  if s == nil: OSError()
+  result.name = $s.h_name
+  result.aliases = cstringArrayToSeq(s.h_aliases)
+  when defined(windows): 
+    result.addrType = TDomain(s.h_addrtype)
+  else:
+    if s.h_addrtype == posix.AF_INET:
+      result.addrType = AF_INET
+    elif s.h_addrtype == posix.AF_INET6:
+      result.addrType = AF_INET6
+    else:
+      OSError("unknown h_addrtype")
+  result.addrList = cstringArrayToSeq(s.h_addr_list)
+  result.length = int(s.h_length)
+
+proc getSockOptInt*(socket: TSocket, level, optname: int): int = 
+  ## getsockopt for integer options.
+  var res: cint
+  var size: cint = sizeof(res)
+  if getsockopt(cint(socket), cint(level), cint(optname), 
+                addr(res), addr(size)) < 0'i32:
+    OSError()
+  result = int(res)
+
+proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
+  ## setsockopt for integer options.
+  var value = cint(optval)
+  if setsockopt(cint(socket), cint(level), cint(optname), addr(value),  
+                sizeof(value)) < 0'i32:
+    OSError()
+
+proc connect*(socket: TSocket, name: string, port = TPort(0), 
+              af: TDomain = AF_INET) =
+  ## well-known connect operation. Already does ``htons`` on the port number,
+  ## so you shouldn't do it.
+  var s: TSockAddrIn
+  s.sin_addr.s_addr = inet_addr(name)
+  s.sin_port = sockets.htons(int16(port))
+  when defined(windows):
+    s.sin_family = toU16(ord(af))
+  else:
+    case af 
+    of AF_UNIX: s.sin_family = posix.AF_UNIX
+    of AF_INET: s.sin_family = posix.AF_INET
+    of AF_INET6: s.sin_family = posix.AF_INET6
+    else: nil
+  if connect(cint(socket), cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32:
+    OSError()
+
+#proc recvfrom*(s: TWinSocket, buf: cstring, len, flags: cint, 
+#               fromm: ptr TSockAddr, fromlen: ptr cint): cint 
+
+#proc sendto*(s: TWinSocket, buf: cstring, len, flags: cint,
+#             to: ptr TSockAddr, tolen: cint): cint
+
+proc createFdSet(fd: var TFdSet, s: seq[TSocket], m: var int) = 
+  FD_ZERO(fd)
+  for i in items(s): 
+    m = max(m, int(i))
+    FD_SET(cint(i), fd)
+   
+proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) = 
+  var i = 0
+  var L = s.len
+  while i < L:
+    if FD_ISSET(cint(s[i]), fd) != 0'i32:
+      s[i] = s[L-1]
+      dec(L)
+    else:
+      inc(i)
+  setLen(s, L)
+
+proc select*(readfds, writefds, exceptfds: var seq[TSocket], 
+             timeout = 500): int = 
+  ## select with a sensible Nimrod interface. `timeout` is in miliseconds.
+  var tv: TTimeVal
+  tv.tv_sec = 0
+  tv.tv_usec = timeout * 1000
+  
+  var rd, wr, ex: TFdSet
+  var m = 0
+  createFdSet((rd), readfds, m)
+  createFdSet((wr), writefds, m)
+  createFdSet((ex), exceptfds, m)
+  
+  result = int(select(cint(m), addr(rd), addr(wr), addr(ex), addr(tv)))
+  
+  pruneSocketSet(readfds, (rd))
+  pruneSocketSet(writefds, (wr))
+  pruneSocketSet(exceptfds, (ex))
+
+proc select*(readfds, writefds: var seq[TSocket], 
+             timeout = 500): int = 
+  ## select with a sensible Nimrod interface. `timeout` is in miliseconds.
+  var tv: TTimeVal
+  tv.tv_sec = 0
+  tv.tv_usec = timeout * 1000
+  
+  var rd, wr: TFdSet
+  var m = 0
+  createFdSet((rd), readfds, m)
+  createFdSet((wr), writefds, m)
+  
+  result = int(select(cint(m), addr(rd), addr(wr), nil, addr(tv)))
+  
+  pruneSocketSet(readfds, (rd))
+  pruneSocketSet(writefds, (wr))
+
+
+proc select*(readfds: var seq[TSocket], timeout = 500): int = 
+  ## select with a sensible Nimrod interface. `timeout` is in miliseconds.
+  var tv: TTimeVal
+  tv.tv_sec = 0
+  tv.tv_usec = timeout * 1000
+  
+  var rd: TFdSet
+  var m = 0
+  createFdSet((rd), readfds, m)
+  
+  result = int(select(cint(m), addr(rd), nil, nil, addr(tv)))
+  
+  pruneSocketSet(readfds, (rd))
+
+
 proc recvLine*(socket: TSocket, line: var string): bool =
-  ## returns false if no further data is available.
+  ## returns false if no further data is available. `line` must be initalized
+  ## and not nil!
   setLen(line, 0)
   while true:
     var c: char
@@ -150,11 +350,11 @@ proc recvLine*(socket: TSocket, line: var string): bool =
     add(line, c)
 
 proc recv*(socket: TSocket, data: pointer, size: int): int =
-  ## receive data from a socket
-  result = posix.recv(cint(socket), data, size, 0'i32)
+  ## receives data from a socket
+  result = recv(cint(socket), data, size, 0'i32)
 
 proc recv*(socket: TSocket): string =
-  ## receive all the data from the socket
+  ## receives all the data from the socket
   const bufSize = 200
   var buf = newString(bufSize)
   result = ""
@@ -173,36 +373,15 @@ proc skip*(socket: TSocket) =
   dealloc(buf)
 
 proc send*(socket: TSocket, data: pointer, size: int): int =
-  result = posix.send(cint(socket), data, size, 0'i32)
+  ## sends data to a socket.
+  result = send(cint(socket), data, size, 0'i32)
 
 proc send*(socket: TSocket, data: string) =
+  ## sends data to a socket.
   if send(socket, cstring(data), data.len) != data.len: OSError()
 
-proc ntohl*(x: int32): int32 = 
-  ## Convert 32-bit integers from network to host byte order.
-  ## On machines where the host byte order is the same as network byte order,
-  ## this is a no-op; otherwise, it performs a 4-byte swap operation.
-  when cpuEndian == bigEndian: result = x
-  else: result = (x shr 24'i32) or
-                 (x shr 8'i32 and 0xff00'i32) or
-                 (x shl 8'i32 and 0xff0000'i32) or
-                 (x shl 24'i32)
-
-proc ntohs*(x: int16): int16 =
-  ## Convert 16-bit integers from network to host byte order. On machines
-  ## where the host byte order is the same as network byte order, this is
-  ## a no-op; otherwise, it performs a 2-byte swap operation.
-  when cpuEndian == bigEndian: result = x
-  else: result = (x shr 8'i16) or (x shl 8'i16)
+when defined(Windows):
+  var wsa: TWSADATA
+  if WSAStartup(0x0101'i16, wsa) != 0: OSError()
 
-proc htonl*(x: int32): int32 =
-  ## Convert 32-bit integers from host to network byte order. On machines
-  ## where the host byte order is the same as network byte order, this is
-  ## a no-op; otherwise, it performs a 4-byte swap operation.
-  result = sockets.ntohl(x)
 
-proc htons*(x: int16): int16 =
-  ## Convert 16-bit positive integers from host to network byte order.
-  ## On machines where the host byte order is the same as network byte
-  ## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
-  result = sockets.ntohs(x)
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index d7fd69f61..1dfb070bc 100755
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -655,8 +655,7 @@ proc replace*(s: string, sub, by: char): string =
 proc delete*(s: var string, first, last: int) =
   ## Deletes in `s` the characters at position `first`..`last`. This modifies
   ## `s` itself, it does not return a copy.
-  var
-    i = first
+  var i = first
   # example: "abc___uvwxyz\0"  (___ is to be deleted)
   # --> first == 3, last == 5
   # s[first..] = s[last+1..]
@@ -851,6 +850,7 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string =
 proc validEmailAddress*(s: string): bool = 
   ## returns true if `s` seems to be a valid e-mail address. 
   ## The checking also uses a domain list.
+  ## Note: This will be moved into another module soon.
   const
     chars = Letters + Digits + {'!','#','$','%','&',
       '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'}
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 8c21b6027..a54af3254 100755
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/lib/system.nim b/lib/system.nim
index 25e914b63..f287d7bda 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -743,6 +743,7 @@ type # these work for most platforms:
   cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
     ## This is binary compatible to the type ``char**`` in *C*. The array's
     ## high value is large enough to disable bounds checking in practice.
+    ## Use cstringArrayToSeq to convert it into a ``seq[string]``.
 
   TEndian* = enum ## is a type describing the endianness of a processor.
     littleEndian, bigEndian
@@ -1468,6 +1469,19 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     echo(errormsg)
     quit(quitFailure)
 
+  proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] =
+    ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
+    ## of length ``len``.
+    newSeq(result, len)
+    for i in 0..len-1: result[i] = $a[i]
+
+  proc cstringArrayToSeq*(a: cstringArray): seq[string] =
+    ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
+    ## terminated by ``nil``.
+    var L = 0
+    while a[L] != nil: inc(L)
+    result = cstringArrayToSeq(a, L)
+
   # ----------------------------------------------------------------------------
 
   include "system/excpt"
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index f384a04e8..ebf0fdc96 100755
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -197,3 +197,147 @@ proc ShellExecute*(HWND: THandle, lpOperation, lpFile,
                    nShowCmd: int32): THandle{.
     stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".}
 
+const
+  WSADESCRIPTION_LEN* = 256
+  WSASYS_STATUS_LEN* = 128
+  FD_SETSIZE* = 64
+  MSG_PEEK* = 2
+  
+  INADDR_ANY* = 0
+  INADDR_LOOPBACK* = 0x7F000001
+  INADDR_BROADCAST* = -1
+  INADDR_NONE* = -1
+  
+type 
+  TWSAData* {.pure, final.} = object 
+    wVersion, wHighVersion: int16
+    szDescription: array[0..WSADESCRIPTION_LEN, char]
+    szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
+    iMaxSockets, iMaxUdpDg: int16
+    lpVendorInfo: cstring
+    
+  TSockAddr* {.pure, final.} = object 
+    sa_family*: int16 # unsigned
+    sa_data: array[0..13, char]
+
+  TInAddr* {.pure, final.} = object ## struct in_addr
+    s_addr*: int32  # IP address
+  
+  Tsockaddr_in* {.pure, final.} = object
+    sin_family*: int16
+    sin_port*: int16 # unsigned
+    sin_addr*: TInAddr
+    sin_zero*: array[0..7, char]
+
+  Tin6_addr* {.pure, final.} = object 
+    bytes*: array[0..15, char]
+
+  Tsockaddr_in6* {.pure, final.} = object
+    sin6_family*: int16
+    sin6_port*: int16 # unsigned
+    sin6_flowinfo*: int32 # unsigned
+    sin6_addr*: Tin6_addr
+    sin6_scope_id*: int32 # unsigned
+
+  Tsockaddr_in6_old* {.pure, final.} = object
+    sin6_family*: int16
+    sin6_port*: int16 # unsigned
+    sin6_flowinfo*: int32 # unsigned
+    sin6_addr*: Tin6_addr
+
+  TServent* {.pure, final.} = object
+    s_name*: cstring
+    s_aliases*: cstringArray
+    when defined(cpu64):
+      s_proto*: cstring
+      s_port*: int16
+    else:
+      s_port*: int16
+      s_proto*: cstring
+
+  Thostent* {.pure, final.} = object
+    h_name*: cstring
+    h_aliases*: cstringArray
+    h_addrtype*: int16
+    h_length*: int16
+    h_addr_list*: cstringArray
+    
+  TWinSocket* = cint
+  
+  TFdSet* {.pure, final.} = object
+    fd_count*: cint # unsigned
+    fd_array*: array[0..FD_SETSIZE-1, TWinSocket]
+    
+  TTimeval* {.pure, final.} = object
+    tv_sec*, tv_usec*: int32
+
+proc getservbyname*(name, proto: cstring): ptr TServent {.
+  stdcall, importc: "getservbyname", dynlib: "Ws2_32.dll".}
+
+proc getservbyport*(port: cint, proto: cstring): ptr TServent {.
+  stdcall, importc: "getservbyport", dynlib: "Ws2_32.dll".}
+
+proc gethostbyname*(name: cstring): ptr THostEnt {.
+  stdcall, importc: "gethostbyname", dynlib: "Ws2_32.dll".}
+
+proc socket*(af, typ, protocol: cint): TWinSocket {.
+  stdcall, importc: "socket", dynlib: "Ws2_32.dll".}
+
+proc closesocket*(s: TWinSocket): cint {.
+  stdcall, importc: "closesocket", dynlib: "Ws2_32.dll".}
+
+proc accept*(s: TWinSocket, a: ptr TSockAddr, addrlen: ptr cint): TWinSocket {.
+  stdcall, importc: "accept", dynlib: "Ws2_32.dll".}
+proc bindSocket*(s: TWinSocket, name: ptr TSockAddr, namelen: cint): cint {.
+  stdcall, importc: "bind", dynlib: "Ws2_32.dll".}
+proc connect*(s: TWinSocket, name: ptr TSockAddr, namelen: cint): cint {.
+  stdcall, importc: "connect", dynlib: "Ws2_32.dll".}
+proc getsockname*(s: TWinSocket, name: ptr TSockAddr, 
+                  namelen: ptr cint): cint {.
+  stdcall, importc: "getsockname", dynlib: "Ws2_32.dll".}
+proc getsockopt*(s: TWinSocket, level, optname: cint, optval: pointer,
+                 optlen: ptr cint): cint {.
+  stdcall, importc: "getsockopt", dynlib: "Ws2_32.dll".}
+proc setsockopt*(s: TWinSocket, level, optname: cint, optval: pointer,
+                 optlen: cint): cint {.
+  stdcall, importc: "setsockopt", dynlib: "Ws2_32.dll".}
+
+proc listen*(s: TWinSocket, backlog: cint): cint {.
+  stdcall, importc: "listen", dynlib: "Ws2_32.dll".}
+proc recv*(s: TWinSocket, buf: pointer, len, flags: cint): cint {.
+  stdcall, importc: "recv", dynlib: "Ws2_32.dll".}
+proc recvfrom*(s: TWinSocket, buf: cstring, len, flags: cint, 
+               fromm: ptr TSockAddr, fromlen: ptr cint): cint {.
+  stdcall, importc: "recvfrom", dynlib: "Ws2_32.dll".}
+proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
+             timeout: ptr TTimeval): cint {.
+  stdcall, importc: "select", dynlib: "Ws2_32.dll".}
+proc send*(s: TWinSocket, buf: pointer, len, flags: cint): cint {.
+  stdcall, importc: "send", dynlib: "Ws2_32.dll".}
+proc sendto*(s: TWinSocket, buf: cstring, len, flags: cint,
+             to: ptr TSockAddr, tolen: cint): cint {.
+  stdcall, importc: "sendto", dynlib: "Ws2_32.dll".}
+
+proc shutdown*(s: TWinSocket, how: cint): cint {.
+  stdcall, importc: "shutdown", dynlib: "Ws2_32.dll".}
+  
+proc inet_addr*(cp: cstring): int32 {.
+  stdcall, importc: "inet_addr", dynlib: "Ws2_32.dll".} 
+
+proc WSAFDIsSet(s: TWinSocket, FDSet: var TFDSet): bool {.
+  stdcall, importc: "__WSAFDIsSet", dynlib: "Ws2_32.dll".}
+
+proc FD_ISSET*(Socket: TWinSocket, FDSet: var TFDSet): cint = 
+  result = if WSAFDIsSet(Socket, FDSet): 1'i32 else: 0'i32
+
+proc FD_SET*(Socket: TWinSocket, FDSet: var TFDSet) = 
+  if FDSet.fd_count < FD_SETSIZE:
+    FDSet.fd_array[int(FDSet.fd_count)] = Socket
+    inc(FDSet.fd_count)
+
+proc FD_ZERO*(FDSet: var TFDSet) =
+  FDSet.fd_count = 0
+
+proc WSAStartup*(wVersionRequired: int16, WSData: var TWSAData): cint {.
+  stdcall, importc: "WSAStartup", dynlib: "Ws2_32.dll".}
+