diff --git a/lib/master.pike b/lib/master.pike
index c739cd9d6ec38e1e7c3749e5b7a4808d804fe8b9..1277bad8bd93298eda55c9f662c095c397d2fe65 100644
--- a/lib/master.pike
+++ b/lib/master.pike
@@ -1,4 +1,4 @@
-/* $Id: master.pike,v 1.63 1998/01/21 19:36:19 hubbe Exp $
+/* $Id: master.pike,v 1.64 1998/01/28 00:28:18 hubbe Exp $
  *
  * Master-file for Pike.
  */
@@ -57,7 +57,7 @@ program compile_string(string data, void|string name)
 
 program compile_file(string file)
 {
-  return compile(cpp(_static_modules.files()->file(file,"r")->read(),file));
+  return compile(cpp(_static_modules.files()->File(file,"r")->read(),file));
 }
 
 
@@ -488,7 +488,7 @@ void _main(string *argv, string *env)
   add_constant("getenv",getenv);
   add_constant("putenv",putenv);
 
-  add_constant("write",_static_modules.files()->file("stdout")->write);
+  add_constant("write",_static_modules.files()->File("stdout")->write);
 
   _master_file_name=backtrace()[-1][0];
   q=explode_path(_master_file_name);
@@ -727,7 +727,7 @@ string handle_include(string f,
 
 string read_include(string f)
 {
-  return _static_modules->files()->file(f,"r")->read();
+  return _static_modules->files()->File(f,"r")->read();
 }
 
 // FIXME
diff --git a/lib/modules/LR.pmod/Grammar_parser.pmod b/lib/modules/LR.pmod/Grammar_parser.pmod
index b287a73b1731e413fc2171dcddeef43d90c5c9e6..3999b96c918dd7be0c9bae0b94a4c5a5dba7ba9f 100755
--- a/lib/modules/LR.pmod/Grammar_parser.pmod
+++ b/lib/modules/LR.pmod/Grammar_parser.pmod
@@ -1,7 +1,7 @@
 #!/home/grubba/src/pike/build/sol2.5/pike
 
 /*
- * $Id: Grammar_parser.pmod,v 1.4 1997/04/22 00:09:28 grubba Exp $
+ * $Id: Grammar_parser.pmod,v 1.5 1998/01/28 00:30:05 hubbe Exp $
  *
  * Generates a parser from a textual specification.
  *
@@ -10,7 +10,7 @@
 
 //.
 //. File:	Grammar_parser.pmod
-//. RCSID:	$Id: Grammar_parser.pmod,v 1.4 1997/04/22 00:09:28 grubba Exp $
+//. RCSID:	$Id: Grammar_parser.pmod,v 1.5 1998/01/28 00:30:05 hubbe Exp $
 //. Author:	Henrik grubbström (grubba@infovav.se)
 //.
 //. Synopsis:	Generates an LR parser from a textual specification.
@@ -375,7 +375,7 @@ object(parser) make_parser(string str, object|void m)
 //. SEE ALSO: Grammar_parser.make_parser
 int|object(parser) make_parser_from_file(string fname, object|void m)
 {
-  object(files.file) f = files.file();
+  object(Stdio.File) f = Stdio.File();
   int|object(parser) g = 0;
   if (f->open(fname, "r")) {
     g = make_parser(f->read(0x7fffffff), m);
diff --git a/lib/modules/Process.pmod b/lib/modules/Process.pmod
index dfa0417077655cefac0e6f229a0122d5a2b03ea0..1ba4be5201801559864e1b9a6f17ac20bd0c10be 100644
--- a/lib/modules/Process.pmod
+++ b/lib/modules/Process.pmod
@@ -112,7 +112,7 @@ string popen(string s)
 
   if (!f) error("Popen failed. (couldn't create pipe)\n");
 
-  p=f->pipe();
+  p=f->pipe(Stdio.PROP_IPC);
   if(!p) error("Popen failed. (couldn't create pipe)\n");
   spawn(s,0,p,0, destruct, f);
   p->close();
diff --git a/lib/modules/Stdio.pmod b/lib/modules/Stdio.pmod
index 8b8d994dbe846941f41c854e881850b630a73f5c..a06918ad3735c717460223e206bed84adf47f535 100644
--- a/lib/modules/Stdio.pmod
+++ b/lib/modules/Stdio.pmod
@@ -1,8 +1,5 @@
 #include <string.h>
-import files;
-
-constant File=file;
-constant Port=port;
+inherit files;
 
 object stderr=File("stderr");
 object stdout=File("stdout");
diff --git a/src/callback.c b/src/callback.c
index 021b2fd07c6e93d80ee082b1e394e5181a29162a..0ff8ca355ce1e3653e9bda54e81b18634f1dab78 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -3,6 +3,7 @@
 ||| Pike is distributed as GPL (General Public License)
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
+#include "global.h"
 #include "pike_macros.h"
 #include "callback.h"
 #include "error.h"
diff --git a/src/configure.in b/src/configure.in
index 7ff094d0c11995d33de1cb0490a2d2bcd9091287..226a8890cbdea28d13a5b9b16cf2e25c22d2ee3a 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,4 +1,4 @@
-AC_REVISION("$Id: configure.in,v 1.153 1998/01/23 02:34:17 grubba Exp $")
+AC_REVISION("$Id: configure.in,v 1.154 1998/01/28 00:31:14 hubbe Exp $")
 AC_INIT(interpret.c)
 AC_CONFIG_HEADER(machine.h)
 
@@ -1732,7 +1732,7 @@ fi
 
 rm -f core
 
-#############################################################################
+##########################################################################
 
 # Set info about shared libraries.
 AC_SUBST(SO)
diff --git a/src/fdlib.c b/src/fdlib.c
index bb7d1f88aa2399ee0bd7744c85485bb8becb04c8..b677f4a9ff0202c905a3db903f072a1e261df6d6 100644
--- a/src/fdlib.c
+++ b/src/fdlib.c
@@ -7,7 +7,7 @@ long da_handle[MAX_OPEN_FILEDESCRIPTORS];
 int fd_type[MAX_OPEN_FILEDESCRIPTORS];
 int first_free_handle;
 
-#define FDDEBUG(X) X
+#define FDDEBUG(X)
 
 char *fd_info(int fd)
 {
@@ -22,10 +22,27 @@ char *fd_info(int fd)
     case FD_SOCKET: return "IS SOCKET";
     case FD_CONSOLE: return "IS CONSOLE";
     case FD_FILE: return "IS FILE";
+    case FD_PIPE: return "IS PIPE";
     default: return "NOT OPEN";
   }
 }
 
+int fd_query_properties(int fd, int guess)
+{
+  switch(fd_type[fd])
+  {
+    case FD_SOCKET:
+      return fd_BUFFERED | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN;
+    case FD_FILE:
+    case FD_CONSOLE:
+      return fd_INTERPROCESSABLE;
+
+    case FD_PIPE:
+      return fd_INTERPROCESSABLE | fd_BUFFERED;
+    default: return 0;
+  }
+}
+
 void fd_init()
 {
   int e;
@@ -137,7 +154,7 @@ FD fd_socket(int domain, int type, int proto)
     errno=EMFILE;
     return -1;
   }
-  s=WSASocket(domain, type, proto, 0, 0, 0);
+  s=socket(domain, type, proto);
   if(s==INVALID_SOCKET)
   {
     errno=WSAGetLastError();
@@ -154,10 +171,40 @@ FD fd_socket(int domain, int type, int proto)
   return fd;
 }
 
+int fd_pipe(int fds[2])
+{
+  HANDLE files[2];
+  if(first_free_handle == FD_NO_MORE_FREE)
+  {
+    errno=EMFILE;
+    return -1;
+  }
+  if(!CreatePipe(&files[0], &files[1], NULL, 0))
+  {
+    errno=GetLastError();
+    return -1;
+  }
+  
+  fds[0]=first_free_handle;
+  first_free_handle=fd_type[fds[0]];
+  fd_type[fds[0]]=FD_PIPE;
+  da_handle[fds[0]]=(long)files[0];
+
+  fds[1]=first_free_handle;
+  first_free_handle=fd_type[fds[1]];
+  fd_type[fds[1]]=FD_PIPE;
+  da_handle[fds[1]]=(long)files[1];
+
+  FDDEBUG(fprintf(stderr,"New pipe: %d (%d) -> %d (%d)\n",fds[0],files[0], fds[1], fds[1]));;
+
+  return 0;
+}
+
 FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen)
 {
   FD new_fd;
   SOCKET s;
+  FDDEBUG(fprintf(stderr,"Accept on %d (%d)..\n",fd,da_handle[fd]));
   if(first_free_handle == FD_NO_MORE_FREE)
   {
     errno=EMFILE;
@@ -168,10 +215,11 @@ FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen)
     errno=ENOTSUPP;
     return -1;
   }
-  s=WSAAccept((SOCKET)da_handle[fd], addr, addrlen, NULL, 0);
+  s=accept((SOCKET)da_handle[fd], addr, addrlen);
   if(s==INVALID_SOCKET)
   {
     errno=WSAGetLastError();
+    FDDEBUG(fprintf(stderr,"Accept failed with errno %d\n",errno));
     return -1;
   }
   
@@ -216,14 +264,13 @@ int PIKE_CONCAT(fd_,NAME) X1 { SOCKET ret; \
 
 
 SOCKFUN2(bind, struct sockaddr *, int)
-#if 1
 int fd_connect (FD fd, struct sockaddr *a, int len)
 {
   SOCKET ret;
-  FDDEBUG(fprintf(stderr, "connect on %d (%d)\n",fd,da_handle[fd])
-  for(ret=0;ret<len;ret++)
-    fprintf(stderr," %02x",((unsigned char *)a)[ret]);
-  fprintf(stderr,"\n");
+  FDDEBUG(fprintf(stderr, "connect on %d (%d)\n",fd,da_handle[fd]);
+	  for(ret=0;ret<len;ret++)
+	  fprintf(stderr," %02x",((unsigned char *)a)[ret]);
+	  fprintf(stderr,"\n");
   )
   if(fd_type[fd] != FD_SOCKET)
   {
@@ -235,9 +282,6 @@ int fd_connect (FD fd, struct sockaddr *a, int len)
   FDDEBUG(fprintf(stderr, "connect returned %d (%d)\n",ret,errno)); 
   return (int)ret; 
 }
-#else
-SOCKFUN2(connect, struct sockaddr *, int)
-#endif
 SOCKFUN4(getsockopt,int,int,void*,int*)
 SOCKFUN4(setsockopt,int,int,void*,int)
 SOCKFUN2(getsockname,struct sockaddr *,int *)
@@ -278,6 +322,7 @@ long fd_write(FD fd, void *buf, long len)
 
     case FD_CONSOLE:
     case FD_FILE:
+    case FD_PIPE:
       if(!WriteFile((HANDLE)da_handle[fd], buf, len, &ret,0) && !ret)
       {
 	errno=GetLastError();
@@ -309,6 +354,7 @@ long fd_read(FD fd, void *to, long len)
 
     case FD_CONSOLE:
     case FD_FILE:
+    case FD_PIPE:
       ret=0;
       if(!ReadFile((HANDLE)da_handle[fd], to, len, &ret,0) && !ret)
       {
@@ -418,7 +464,7 @@ int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t)
 int fd_ioctl(FD fd, int cmd, void *data)
 {
   int ret;
-  FDEBUG(fprintf("ioctl(%d (%d,%d,%p)\n",fd,da_handle[fd],cmd,data))
+  FDDEBUG(fprintf(stderr,"ioctl(%d (%d,%d,%p)\n",fd,da_handle[fd],cmd,data));
   switch(fd_type[fd])
   {
     case FD_SOCKET:
@@ -740,7 +786,7 @@ struct fd_waitor
  fd_FDZERO(&X->xcustomers); \
  } while(0)
 
-void fd_waitor_set_customer(fd_waitor *x, FD customer, int flags)
+void fd_waitor_set_customer(struct fd_waitor *x, FD customer, int flags)
 {
   if(flags & FD_EVENT_READ)
   {
diff --git a/src/fdlib.h b/src/fdlib.h
index fc7139899d5862e8c91c0c38f1b9a462ca706687..272b3553cf8c79d2bc246fd68e8492d4a65308ee 100644
--- a/src/fdlib.h
+++ b/src/fdlib.h
@@ -20,9 +20,20 @@
 #include <sys/stat.h>
 #endif
 
+
+#define fd_INTERPROCESSABLE   1
+#define fd_CAN_NONBLOCK       2
+#define fd_CAN_SHUTDOWN       4
+#define fd_BUFFERED           8
+#define fd_BIDIRECTIONAL     16
+
 #ifdef HAVE_WINSOCK2_H
 
 
+#define FILE_CAPABILITIES (fd_INTERPROCESSABLE)
+#define PIPE_CAPABILITIES (fd_INTERPROCESSABLE | fd_BUFFERED)
+#define SOCKET_CAPABILITIES (fd_BIDIRECTIONAL | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN)
+
 #ifndef FD_SETSIZE
 #define FD_SETSIZE MAX_OPEN_FILEDESCRIPTORS
 #endif
@@ -40,13 +51,15 @@ typedef int FD;
 
 /* Prototypes begin here */
 char *fd_info(int fd);
+int fd_query_query_properties(int fd, int guess);
 void fd_init();
 void fd_exit();
 FD fd_open(char *file, int open_mode, int create_mode);
 FD fd_socket(int domain, int type, int proto);
+int fd_pipe(int fds[2]);
 FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen);
 SOCKFUN2(bind, struct sockaddr *, int)
-SOCKFUN2(connect, struct sockaddr *, int)
+int fd_connect (FD fd, struct sockaddr *a, int len);
 SOCKFUN4(getsockopt,int,int,void*,int*)
 SOCKFUN4(setsockopt,int,int,void*,int)
 SOCKFUN2(getsockname,struct sockaddr *,int *)
@@ -65,6 +78,22 @@ int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t);
 int fd_ioctl(FD fd, int cmd, void *data);
 FD fd_dup(FD from);
 FD fd_dup2(FD from, FD to);
+struct fd_mapper;
+void init_fd_mapper(struct fd_mapper *x);
+void exit_fd_mapper(struct fd_mapper *x);
+void fd_mapper_set(struct fd_mapper *x, FD fd, void *data);
+void *fd_mapper_get(struct fd_mapper *x, FD fd);
+struct fd_mapper_data;
+struct fd_mapper;
+void init_fd_mapper(struct fd_mapper *x);
+void exit_fd_mapper(struct fd_mapper *x);
+void fd_mapper_set(struct fd_mapper *x, FD fd, void *data);
+void *fd_mapper_get(struct fd_mapper *x, FD fd);
+struct fd_data_hash;
+struct fd_data_hash_block;
+int get_fd_data_key(void);
+void store_fd_data(FD fd, int key, void *data);
+void *get_fd_data(FD fd, int key);
 /* Prototypes end here */
 
 #undef SOCKFUN1
@@ -101,6 +130,7 @@ FD fd_dup2(FD from, FD to);
 #define fd_shutdown_write SD_SEND
 #define fd_shutdown_both SD_BOTH
 
+#define FD_PIPE -5
 #define FD_SOCKET -4
 #define FD_CONSOLE -3
 #define FD_FILE -2
@@ -173,11 +203,13 @@ typedef int FD;
 #define fd_TRUNC O_TRUNC
 #define fd_EXCL O_EXCL
 
+#define fd_query_properties(X,Y) ( fd_INTERPROCESSABLE | (Y))
 #define fd_open open
 #define fd_close close
 #define fd_read read
 #define fd_write write
 #define fd_ioctl ioctl
+#define fd_pipe pipe
 
 #define fd_socket socket
 #define fd_bind bind
@@ -198,6 +230,7 @@ typedef int FD;
 #define fd_listen listen
 
 #define fd_select select
+#define fd_socketpair socketpair
 
 #define fd_fd_set fd_set
 #define fd_FD_CLR FD_CLR
@@ -222,6 +255,11 @@ typedef struct my_fd_set_s
 #define fd_copy_my_fd_set_to_fd_set(TO,FROM,max) \
    MEMCPY((TO),&(FROM)->tmp,sizeof(*(TO)))
 
+#define FILE_CAPABILITIES (fd_INTERPROCESSABLE)
+#define PIPE_CAPABILITIES (fd_INTERPROCESSABLE | fd_BUFFERED)
+#define UNIX_SOCKET_CAPABILITIES (fd_INTERPROCESSABLE | fd_BIDIRECTIONAL | fd_CAN_NONBLOCK)
+#define SOCKET_CAPABILITIES (fd_INTERPROCESSABLE | fd_BIDIRECTIONAL | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN)
+
 #endif
 
 #endif
diff --git a/src/modules/files/configure.in b/src/modules/files/configure.in
index 315010b15d9455c6885d83d67bbd5165c534eba4..59a01916dd71534324beaa6e8ccf38c8f7097622 100644
--- a/src/modules/files/configure.in
+++ b/src/modules/files/configure.in
@@ -11,7 +11,7 @@ AC_HEADER_DIRENT
 AC_CHECK_LIB(bind, __inet_ntoa)
 AC_CHECK_LIB(socket, socket)
 
-AC_HAVE_FUNCS(getwd perror readdir_r statvfs statfs ustat lstat)
+AC_HAVE_FUNCS(getwd perror readdir_r statvfs statfs ustat lstat socketpair)
 
 AC_MSG_CHECKING(if mkdir takes 1 or 2 arguments)
 AC_CACHE_VAL(pike_cv_func_mkdir_args,[
@@ -465,7 +465,7 @@ int main()
 
 AC_MSG_RESULT($pike_cv_select_on_unix_sockets)
 if test x$pike_cv_select_on_unix_sockets = xyes ; then
-  AC_DEFINE(HAVE_SOCKETPAIR)
+  AC_DEFINE(UNIX_SOCKETS_WORKS_WITH_SHUTDOWN)
 fi
 
 
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 209693236553c90f10534f879ed50387597e6b1e..56e00e1e1ffd6b200866cab797dd2da0e184b52d 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 8192
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.69 1998/01/25 08:28:00 hubbe Exp $");
+RCSID("$Id: file.c,v 1.70 1998/01/28 00:33:15 hubbe Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -559,6 +559,14 @@ static void file_close(INT32 args)
     flags=FILE_READ | FILE_WRITE;
   }
 
+  if((files[FD].open_mode & ~flags & (FILE_READ|FILE_WRITE)) && flags)
+  {
+    if(!(files[FD].open_mode & fd_CAN_SHUTDOWN))
+    {
+      error("Cannot close one direction on this file.\n");
+    }
+  }
+
   if(do_close(FD,flags))
     FD=-1;
   pop_n_elems(args);
@@ -618,7 +626,8 @@ static void file_open(INT32 args)
   }
   else
   {
-    init_fd(fd,flags);
+    
+    init_fd(fd,flags | fd_query_properties(fd, FILE_CAPABILITIES));
     FD=fd;
     ERRNO = 0;
     set_close_on_exec(fd,1);
@@ -813,6 +822,9 @@ static void file_set_nonblocking(INT32 args)
 {
   if(FD < 0) error("File not open.\n");
 
+  if(!(files[FD].open_mode & fd_CAN_NONBLOCK))
+    error("That file does not support nonblocking operation.\n");
+
   switch(args)
   {
   default: pop_n_elems(args-3);
@@ -828,6 +840,9 @@ static void file_set_nonblocking(INT32 args)
 
 static void file_set_blocking(INT32 args)
 {
+  if(!(files[FD].open_mode & fd_CAN_NONBLOCK))
+    error("That file does not support nonblocking operation.\n");
+
   free_svalue(& THIS->read_callback);
   THIS->read_callback.type=T_INT;
   THIS->read_callback.u.integer=0;
@@ -921,11 +936,11 @@ static void file_query_close_callback(INT32 args)
   assign_svalue_no_free(sp++,& THIS->close_callback);
 }
 
-struct object *file_make_object_from_fd(int fd, int mode)
+struct object *file_make_object_from_fd(int fd, int mode, int guess)
 {
   struct object *o;
 
-  init_fd(fd, mode);
+  init_fd(fd, mode | fd_query_properties(fd, guess));
   o=clone_object(file_program,0);
   ((struct file_struct *)(o->storage))->fd=fd;
   ((struct file_struct *)(o->storage))->my_errno=0;
@@ -977,8 +992,6 @@ static void file_set_buffer(INT32 args)
 }
 
 
-#ifndef HAVE_SOCKETPAIR
-
 /* No socketpair() ?
  * No AF_UNIX sockets ?
  * No hope ?
@@ -994,7 +1007,6 @@ static void file_set_buffer(INT32 args)
  * collide with any libs or headers. Also useful when testing
  * this code on a system that _has_ socketpair...
  */
-#define socketpair socketpair_ultra
 
 /* Protected since errno may expand to a function call. */
 #ifndef errno
@@ -1005,7 +1017,7 @@ int my_socketpair(int family, int type, int protocol, int sv[2])
   static int fd=-1;
   static struct sockaddr_in my_addr;
   struct sockaddr_in addr,addr2;
-  int len;
+  int len,retries=0;
 
   MEMSET((char *)&addr,0,sizeof(struct sockaddr_in));
 
@@ -1056,6 +1068,8 @@ int my_socketpair(int family, int type, int protocol, int sv[2])
       return -1;
     }
 
+    set_nonblocking(fd,1);
+
     my_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
   }
   
@@ -1064,27 +1078,31 @@ int my_socketpair(int family, int type, int protocol, int sv[2])
 
 /*  set_nonblocking(sv[1],1); */
 
+retry_connect:
+  retries++;
   if(fd_connect(sv[1], (struct sockaddr *)&my_addr, sizeof(addr)) < 0)
   {
-    int tmp2;
-    for(tmp2=0;tmp2<20;tmp2++)
+    fprintf(stderr,"errno=%d (%d)\n",errno,EWOULDBLOCK);
+    if(errno != EWOULDBLOCK)
     {
-      int tmp;
-      len=sizeof(addr);
-      tmp=fd_accept(fd,(struct sockaddr *)&addr,&len);
-
-      if(tmp!=-1) fd_close(tmp);
-      if(fd_connect(sv[1], (struct sockaddr *)&my_addr, sizeof(my_addr))>=0)
-	break;
+      int tmp2;
+      for(tmp2=0;tmp2<20;tmp2++)
+      {
+	int tmp;
+	len=sizeof(addr);
+	tmp=fd_accept(fd,(struct sockaddr *)&addr,&len);
+	
+	if(tmp!=-1)
+	  fd_close(tmp);
+	else
+	  break;
+      }
+      if(retries > 20) return -1;
+      goto retry_connect;
     }
-    if(tmp2>=20)
-      return -1;
   }
 
 
-  len=sizeof(addr);
-  if(fd_getsockname(sv[1],(struct sockaddr *)&addr2,&len) < 0) return -1;
-
   /* Accept connection
    * Make sure this connection was our OWN connection,
    * otherwise some wizeguy could interfere with our
@@ -1095,9 +1113,11 @@ int my_socketpair(int family, int type, int protocol, int sv[2])
   do
   {
     len=sizeof(addr);
+  retry_accept:
     sv[0]=fd_accept(fd,(struct sockaddr *)&addr,&len);
 
     if(sv[0] < 0) {
+      if(errno==EINTR) goto retry_accept;
       fd_close(sv[1]);
       return -1;
     }
@@ -1105,17 +1125,18 @@ int my_socketpair(int family, int type, int protocol, int sv[2])
     /* We do not trust accept */
     len=sizeof(addr);
     if(fd_getpeername(sv[0], (struct sockaddr *)&addr,&len)) return -1;
+    len=sizeof(addr);
+    if(fd_getsockname(sv[1],(struct sockaddr *)&addr2,&len) < 0) return -1;
   }while(len < (int)sizeof(addr) ||
 	 addr2.sin_addr.s_addr != addr.sin_addr.s_addr ||
 	 addr2.sin_port != addr.sin_port);
 
-/*   set_nonblocking(sv[1],0); */
-
+/*  set_nonblocking(sv[1],0); */
 
   return 0;
 }
 
-int socketpair(int family, int type, int protocol, int sv[2])
+int socketpair_ultra(int family, int type, int protocol, int sv[2])
 {
   int retries=0;
 
@@ -1138,18 +1159,59 @@ int socketpair(int family, int type, int protocol, int sv[2])
   }
 }
 
-
+#ifndef HAVE_SOCKETPAIR
+#define socketpair socketpair_ultra
 #endif
 
 static void file_pipe(INT32 args)
 {
   int inout[2],i;
+
+  int type=fd_CAN_NONBLOCK | fd_BIDIRECTIONAL;
+
+  check_all_args("file->pipe",args, BIT_INT | BIT_VOID, 0);
+  if(args) type = sp[-args].u.integer;;
+
   do_close(FD,FILE_READ | FILE_WRITE);
   FD=-1;
   pop_n_elems(args);
   ERRNO=0;
 
-  i=socketpair(AF_UNIX, SOCK_STREAM, 0, &inout[0]);
+  do
+  {
+#ifdef PIPE_CAPABILITIES
+    if(!(type & ~(PIPE_CAPABILITIES)))
+    {
+      i=fd_pipe(&inout[0]);
+      type=PIPE_CAPABILITIES;
+      break;
+    }
+#endif
+
+#ifdef UNIX_SOCKETS_WORK_WITH_SHUTDOWN
+#undef UNIX_SOCKET_CAPABILITIES
+#define UNIX_SOCKET_CAPABILITIES (fd_INTERPROCESSABLE | fd_BIDIRECTIONAL | fd_CAN_NONBLOCK | fd_CAN_SHUTDOWN)
+#endif
+
+#if defined(HAVE_SOCKETPAIR)
+    if(!(type & ~(UNIX_SOCKET_CAPABILITIES)))
+    {
+      i=fd_socketpair(AF_UNIX, SOCK_STREAM, 0, &inout[0]);
+      type=UNIX_SOCKET_CAPABILITIES;
+      break;
+    }
+#endif
+    
+    if(!(type & ~(SOCKET_CAPABILITIES)))
+    {
+      i=socketpair_ultra(AF_UNIX, SOCK_STREAM, 0, &inout[0]);
+      type=SOCKET_CAPABILITIES;
+      break;
+    }
+    
+    error("Cannot create a pipe patching those parameters.\n");
+  }while(0);
+    
   if(i<0)
   {
     ERRNO=errno;
@@ -1165,18 +1227,18 @@ static void file_pipe(INT32 args)
   }
   else
   {
-    init_fd(inout[0],FILE_READ | FILE_WRITE);
-
+    init_fd(inout[0],FILE_READ | (type&fd_BIDIRECTIONAL?FILE_WRITE:0) |
+	    fd_query_properties(inout[0], type));
+    
     my_set_close_on_exec(inout[0],1);
     my_set_close_on_exec(inout[1],1);
     FD=inout[0];
-
+    
     ERRNO=0;
-    push_object(file_make_object_from_fd(inout[1],FILE_READ | FILE_WRITE));
+    push_object(file_make_object_from_fd(inout[1], (type&fd_BIDIRECTIONAL?FILE_READ:0)| FILE_WRITE,type));
   }
 }
 
-
 static void init_file_struct(struct object *o)
 {
   FD=-1;
@@ -1365,7 +1427,7 @@ static void file_open_socket(INT32 args)
     }
   }
 
-  init_fd(fd, FILE_READ | FILE_WRITE);
+  init_fd(fd, FILE_READ | FILE_WRITE | fd_query_properties(fd, SOCKET_CAPABILITIES));
   my_set_close_on_exec(fd,1);
   FD = fd;
   ERRNO=0;
@@ -1604,9 +1666,9 @@ void pike_module_init(void)
     files[e].refs=0;
   }
 
-  init_fd(0, FILE_READ);
-  init_fd(1, FILE_WRITE);
-  init_fd(2, FILE_WRITE);
+  init_fd(0, FILE_READ | fd_query_properties(0,fd_CAN_NONBLOCK));
+  init_fd(1, FILE_WRITE | fd_query_properties(1,fd_CAN_NONBLOCK));
+  init_fd(2, FILE_WRITE | fd_query_properties(2,fd_CAN_NONBLOCK));
 
   init_files_efuns();
 #if 0
@@ -1660,9 +1722,15 @@ void pike_module_init(void)
   set_gc_mark_callback(gc_mark_file_struct);
 
   file_program=end_program();
-  add_program_constant("file",file_program,0);
+  add_program_constant("File",file_program,0);
 
   port_setup_program();
+
+  add_integer_constant("PROP_IPC",fd_INTERPROCESSABLE,0);
+  add_integer_constant("PROP_NONBLOCK",fd_CAN_NONBLOCK,0);
+  add_integer_constant("PROP_SHUTDOWN",fd_CAN_SHUTDOWN,0);
+  add_integer_constant("PROP_BUFFERED",fd_BUFFERED,0);
+  add_integer_constant("PROP_BIDIRECTIONAL",fd_BIDIRECTIONAL,0);
   
   add_gc_callback(mark_ids, 0, 0);
 }
diff --git a/src/modules/files/file.h b/src/modules/files/file.h
index e1856e6881406eb6f77a115847350e00dcc98557..a556e2c9c4e0a84637981a22405f565b573671fa 100644
--- a/src/modules/files/file.h
+++ b/src/modules/files/file.h
@@ -39,20 +39,23 @@ extern void get_inet_addr(struct sockaddr_in *addr,char *name);
 struct file_struct;
 void my_set_close_on_exec(int fd, int to);
 void do_set_close_on_exec(void);
-struct object *file_make_object_from_fd(int fd, int mode);
+struct object *file_make_object_from_fd(int fd, int mode, int guess);
+int my_socketpair(int family, int type, int protocol, int sv[2]);
 int socketpair(int family, int type, int protocol, int sv[2]);
-void exit_files(void);
+void pike_module_exit(void);
 void mark_ids(struct callback *foo, void *bar, void *gazonk);
-void init_files_programs(void);
+void pike_module_init(void);
+int pike_make_pipe(int *fds);
 /* Prototypes end here */
 
-#define FILE_READ 1
-#define FILE_WRITE 2
-#define FILE_APPEND 4
-#define FILE_CREATE 8
-#define FILE_TRUNC 16
-#define FILE_EXCLUSIVE 32
-#define FILE_NONBLOCKING 64
-#define FILE_SET_CLOSE_ON_EXEC 128
+#define FILE_READ               0x1000
+#define FILE_WRITE              0x2000
+#define FILE_APPEND             0x4000
+#define FILE_CREATE             0x8000
+#define FILE_TRUNC              0x0100
+#define FILE_EXCLUSIVE          0x0200
+#define FILE_NONBLOCKING        0x0400
+#define FILE_SET_CLOSE_ON_EXEC  0x0800
+
 
 #endif
diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c
index 1f89819ea4d78e12ff6ca32b88619ee5d1e04066..cb75f7edc270d8670a090dfdc0922a5c3b149d9f 100644
--- a/src/modules/files/socket.c
+++ b/src/modules/files/socket.c
@@ -333,7 +333,7 @@ static void port_accept(INT32 args)
   }
 
   my_set_close_on_exec(fd,1);
-  o=file_make_object_from_fd(fd,FILE_READ | FILE_WRITE);
+  o=file_make_object_from_fd(fd,FILE_READ | FILE_WRITE, SOCKET_CAPABILITIES);
   
   pop_n_elems(args);
   push_object(o);
@@ -408,6 +408,6 @@ void port_setup_program(void)
   set_init_callback(init_port_struct);
   set_exit_callback(exit_port_struct);
 
-  end_class("port",0);
+  end_class("Port",0);
 }
 
diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike
index 9b65cb5db27d93921bccc16a0dc746636fb9d8b7..47235b6290ab2f728c2485e1cc7b190b1ce7d083 100755
--- a/src/modules/files/socktest.pike
+++ b/src/modules/files/socktest.pike
@@ -1,6 +1,6 @@
 #!/usr/local/bin/pike
 
-/* $Id: socktest.pike,v 1.7 1998/01/25 08:28:01 hubbe Exp $ */
+/* $Id: socktest.pike,v 1.8 1998/01/28 00:33:17 hubbe Exp $ */
 
 import Stdio;
 import String;
@@ -176,7 +176,9 @@ object *spair(int type)
       exit(1);
     }
   }else{
-    sock2=sock1->pipe();
+    sock2=sock1->pipe(Stdio.PROP_BIDIRECTIONAL |
+		      Stdio.PROP_NONBLOCK |
+		      Stdio.PROP_SHUTDOWN);
     if(!sock2)
     {
       werror("File->pipe() failed 0\n");
diff --git a/src/modules/files/testsuite.in b/src/modules/files/testsuite.in
index ad77b2b7c3096119a58fdd5f4391b21f63674f03..2a238037ad954b400bb698c80ba6075278f32c72 100644
--- a/src/modules/files/testsuite.in
+++ b/src/modules/files/testsuite.in
@@ -92,7 +92,6 @@ test_true(arrayp(get_dir(".")))
 // - cd
 // - getcwd
 test_true(stringp(getcwd()))
-test_eq('/',getcwd()[0])
 
 // strerror
 cond([[all_constants()->strerror]],
diff --git a/src/program.c b/src/program.c
index 4a101fc72bddae14bd6fde770203023a295cff33..e1821cf52d0e82f57486029dea5012b249b36397 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.57 1998/01/27 20:02:15 hubbe Exp $");
+RCSID("$Id: program.c,v 1.58 1998/01/28 00:31:17 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -914,6 +914,12 @@ void low_inherit(struct program *p,
     return;
   }
 
+  if(!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE)))
+  {
+    yyerror("Cannot inherit program which is not fully compiled yet.");
+    return;
+  }
+
   inherit_offset = new_program->num_inherits;
 
   storage_offset=new_program->storage_needed;
@@ -2154,6 +2160,16 @@ struct program *program_from_svalue(struct svalue *s)
 {
   switch(s->type)
   {
+    case T_OBJECT:
+    {
+      struct program *p;
+      push_svalue(s);
+      f_object_program(1);
+      p=program_from_svalue(sp-1);
+      pop_stack();
+      return p; /* We trust that there is a reference somewhere... */
+    }
+
   case T_FUNCTION:
     return program_from_function(s);
   case T_PROGRAM: