]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
(Fmove_to_column): Remove unused local variable `end_byte'.
[gnu-emacs] / src / w32.c
index 243948c0a03edfdce3853e1d4a0331dc14d89726..718869978e4c22999224750af573387b0e29dc74 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,5 +1,5 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -35,7 +35,11 @@ Boston, MA 02111-1307, USA.
 #include <sys/utime.h>
 
 /* must include CRT headers *before* config.h */
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #undef access
 #undef chdir
 #undef chmod
@@ -63,6 +67,10 @@ Boston, MA 02111-1307, USA.
 
 #include <pwd.h>
 
+#ifdef __GNUC__
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+#endif
 #include <windows.h>
 
 #ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
@@ -77,22 +85,43 @@ Boston, MA 02111-1307, USA.
 #undef gethostbyname
 #undef getservbyname
 #undef shutdown
+#undef setsockopt
+#undef listen
+#undef getsockname
+#undef accept
+#undef recvfrom
+#undef sendto
 #endif
 
 #include "w32.h"
 #include "ndir.h"
 #include "w32heap.h"
-#undef min
-#undef max
-#define min(x, y) (((x) < (y)) ? (x) : (y))
-#define max(x, y) (((x) > (y)) ? (x) : (y))
+#include "systime.h"
 
 extern Lisp_Object Vw32_downcase_file_names;
 extern Lisp_Object Vw32_generate_fake_inodes;
 extern Lisp_Object Vw32_get_true_file_attributes;
 extern Lisp_Object Vw32_num_mouse_buttons;
 
+\f
+/* Equivalent of strerror for W32 error codes.  */
+char *
+w32_strerror (int error_no)
+{
+  static char buf[500];
+
+  if (error_no == 0)
+    error_no = GetLastError ();
+
+  buf[0] = '\0';
+  if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+                     error_no,
+                     0, /* choose most suitable language */
+                     buf, sizeof (buf), NULL))
+    sprintf (buf, "w32 error %u", error_no);
+  return buf;
+}
+
 static char startup_dir[MAXPATHLEN];
 
 /* Get the current working directory.  */
@@ -656,7 +685,6 @@ extern Lisp_Object Vsystem_configuration;
 void
 init_environment (char ** argv)
 {
-  int len;
   static const char * const tempdirs[] = {
     "$TMPDIR", "$TEMP", "$TMP", "c:/"
   };
@@ -677,11 +705,11 @@ init_environment (char ** argv)
         read-only filesystem, like CD-ROM or a write-protected floppy.
         The only way to be really sure is to actually create a file and
         see if it succeeds.  But I think that's too much to ask.  */
-      if (tmp && access (tmp, D_OK) == 0)
+      if (tmp && _access (tmp, D_OK) == 0)
        {
          char * var = alloca (strlen (tmp) + 8);
          sprintf (var, "TMPDIR=%s", tmp);
-         putenv (var);
+         _putenv (strdup (var));
          break;
        }
     }
@@ -698,6 +726,7 @@ init_environment (char ** argv)
     int i;
     LPBYTE lpval;
     DWORD dwType;
+    char locale_name[32];
 
     static struct env_entry
     {
@@ -708,7 +737,7 @@ init_environment (char ** argv)
       {"HOME", "C:/"},
       {"PRELOAD_WINSOCK", NULL},
       {"emacs_dir", "C:/emacs"},
-      {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
+      {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
       {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
       {"EMACSDATA", "%emacs_dir%/etc"},
       {"EMACSPATH", "%emacs_dir%/bin"},
@@ -717,9 +746,25 @@ init_environment (char ** argv)
         is then ignored.  */
       /*  {"INFOPATH", "%emacs_dir%/info"},  */
       {"EMACSDOC", "%emacs_dir%/etc"},
-      {"TERM", "cmd"}
+      {"TERM", "cmd"},
+      {"LANG", NULL},
     };
 
+  /* Get default locale info and use it for LANG.  */
+  if (GetLocaleInfo (LOCALE_USER_DEFAULT,
+                     LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
+                     locale_name, sizeof (locale_name)))
+    {
+      for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
+        {
+          if (strcmp (env_vars[i].name, "LANG") == 0)
+            {
+              env_vars[i].def_value = locale_name;
+              break;
+            }
+        }
+    }
+
 #define SET_ENV_BUF_SIZE (4 * MAX_PATH)        /* to cover EMACSLOADPATH */
 
     /* Treat emacs_dir specially: set it unconditionally based on our
@@ -744,11 +789,11 @@ init_environment (char ** argv)
            if (*p == '\\') *p = '/';
                  
          _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
-         putenv (strdup (buf));
+         _putenv (strdup (buf));
        }
     }
 
-    for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) 
+    for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
       {
        if (!getenv (env_vars[i].name))
          {
@@ -769,14 +814,14 @@ init_environment (char ** argv)
 
                    ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
                    _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, buf1);
-                   putenv (strdup (buf2));
+                   _putenv (strdup (buf2));
                  }
                else if (dwType == REG_SZ)
                  {
                    char buf[SET_ENV_BUF_SIZE];
                  
                    _snprintf (buf, sizeof(buf)-1, "%s=%s", env_vars[i].name, lpval);
-                   putenv (strdup (buf));
+                   _putenv (strdup (buf));
                  }
 
                if (!dont_free)
@@ -840,18 +885,32 @@ init_environment (char ** argv)
   init_user_info ();
 }
 
+char *
+emacs_root_dir (void)
+{
+  static char root_dir[FILENAME_MAX];
+  const char *p;
+
+  p = getenv ("emacs_dir");
+  if (p == NULL)
+    abort ();
+  strcpy (root_dir, p);
+  root_dir[parse_root (root_dir, NULL)] = '\0';
+  dostounix_filename (root_dir);
+  return root_dir;
+}
+
 /* We don't have scripts to automatically determine the system configuration
    for Emacs before it's compiled, and we don't want to have to make the
    user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
    routine.  */
 
-static char configuration_buffer[32];
-
 char *
 get_emacs_configuration (void)
 {
   char *arch, *oem, *os;
   int build_num;
+  static char configuration_buffer[32];
 
   /* Determine the processor type.  */
   switch (get_processor_type ()) 
@@ -890,8 +949,17 @@ get_emacs_configuration (void)
       break;
     }
 
-  /* Let oem be "*" until we figure out how to decode the OEM field.  */
-  oem = "*";
+  /* Use the OEM field to reflect the compiler/library combination.  */
+#ifdef _MSC_VER
+#define COMPILER_NAME  "msvc"
+#else
+#ifdef __GNUC__
+#define COMPILER_NAME  "mingw"
+#else
+#define COMPILER_NAME  "unknown"
+#endif
+#endif
+  oem = COMPILER_NAME;
 
   switch (osinfo_cache.dwPlatformId) {
   case VER_PLATFORM_WIN32_NT:
@@ -927,13 +995,45 @@ get_emacs_configuration (void)
   return configuration_buffer;
 }
 
+char *
+get_emacs_configuration_options (void)
+{
+  static char options_buffer[256];
+
+/* Work out the effective configure options for this build.  */
+#ifdef _MSC_VER
+#define COMPILER_VERSION       "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
+#else
+#ifdef __GNUC__
+#define COMPILER_VERSION       "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
+#else
+#define COMPILER_VERSION       ""
+#endif
+#endif
+
+  sprintf (options_buffer, COMPILER_VERSION);
+#ifdef EMACSDEBUG
+  strcat (options_buffer, " --no-opt");
+#endif
+#ifdef USER_CFLAGS
+  strcat (options_buffer, " --cflags");
+  strcat (options_buffer, USER_CFLAGS);
+#endif
+#ifdef USER_LDFLAGS
+  strcat (options_buffer, " --ldflags");
+  strcat (options_buffer, USER_LDFLAGS);
+#endif
+  return options_buffer;
+}
+
+
 #include <sys/timeb.h>
 
 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95).  */
 void 
 gettimeofday (struct timeval *tv, struct timezone *tz)
 {
-  struct _timeb tb;
+  struct timeb tb;
   _ftime (&tb);
 
   tv->tv_sec = tb.time;
@@ -1024,7 +1124,7 @@ lookup_volume_info (char * root_dir)
 static void
 add_volume_info (char * root_dir, volume_info_data * info)
 {
-  info->root_dir = strdup (root_dir);
+  info->root_dir = xstrdup (root_dir);
   info->next = volume_cache;
   volume_cache = info;
 }
@@ -1107,15 +1207,15 @@ GetCachedVolumeInformation (char * root_dir)
       }
     else
       {
-       free (info->name);
-       free (info->type);
+       xfree (info->name);
+       xfree (info->type);
       }
 
-    info->name = strdup (name);
+    info->name = xstrdup (name);
     info->serialnum = serialnum;
     info->maxcomp = maxcomp;
     info->flags = flags;
-    info->type = strdup (type);
+    info->type = xstrdup (type);
     info->timestamp = GetTickCount ();
   }
 
@@ -1200,7 +1300,7 @@ map_w32_filename (const char * name, const char ** pPath)
       return shortname;
     }
 
-  if (is_fat_volume (name, &path)) /* truncate to 8.3 */
+  if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
     {
       register int left = 8;   /* maximum number of chars in part */
       register int extn = 0;   /* extension added? */
@@ -1453,9 +1553,9 @@ open_unc_volume (char *path)
 char *
 read_unc_volume (HANDLE henum, char *readbuf, int size)
 {
-  int count;
+  DWORD count;
   int result;
-  int bufsize = 512;
+  DWORD bufsize = 512;
   char *buffer;
   char *ptr;
 
@@ -1739,14 +1839,20 @@ sys_mktemp (char * template)
 int
 sys_open (const char * path, int oflag, int mode)
 {
-  /* Force all file handles to be non-inheritable. */
-  return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
+  const char* mpath = map_w32_filename (path, NULL);
+  /* Try to open file without _O_CREAT, to be able to write to hidden
+     and system files. Force all file handles to be
+     non-inheritable. */
+  int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
+  if (res >= 0)
+    return res;
+  return _open (mpath, oflag | _O_NOINHERIT, mode);
 }
 
 int
 sys_rename (const char * oldname, const char * newname)
 {
-  int result;
+  BOOL result;
   char temp[MAX_PATH];
 
   /* MoveFile on Windows 95 doesn't correctly change the short file name
@@ -1790,7 +1896,7 @@ sys_rename (const char * oldname, const char * newname)
          result = rename (oldname, temp);
        }
       /* This loop must surely terminate!  */
-      while (result < 0 && (errno == EEXIST || errno == EACCES));
+      while (result < 0 && errno == EEXIST);
       if (result < 0)
        return -1;
     }
@@ -1810,7 +1916,7 @@ sys_rename (const char * oldname, const char * newname)
   result = rename (temp, newname);
 
   if (result < 0
-      && (errno == EEXIST || errno == EACCES)
+      && errno == EEXIST
       && _chmod (newname, 0666) == 0
       && _unlink (newname) == 0)
     result = rename (temp, newname);
@@ -2321,7 +2427,18 @@ unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
 int (PASCAL *pfn_gethostname) (char * name, int namelen);
 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
-  
+
+int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
+                             const char * optval, int optlen);
+int (PASCAL *pfn_listen) (SOCKET s, int backlog);
+int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
+                              int * namelen);
+SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
+int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
+                      struct sockaddr * from, int * fromlen);
+int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
+                         const struct sockaddr * to, int tolen);
+
 /* SetHandleInformation is only needed to make sockets non-inheritable. */
 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
 #ifndef HANDLE_FLAG_INHERIT
@@ -2391,7 +2508,12 @@ init_winsock (int load_now)
       LOAD_PROC( gethostbyname );
       LOAD_PROC( getservbyname );
       LOAD_PROC( WSACleanup );
-
+      LOAD_PROC( setsockopt );
+      LOAD_PROC( listen );
+      LOAD_PROC( getsockname );
+      LOAD_PROC( accept );
+      LOAD_PROC( recvfrom );
+      LOAD_PROC( sendto );
 #undef LOAD_PROC
 
       /* specify version 1.1 of winsock */
@@ -2539,8 +2661,8 @@ sys_strerror(int error_no)
   int i;
   static char unknown_msg[40];
 
-  if (error_no >= 0 && error_no < _sys_nerr)
-    return _sys_errlist[error_no];
+  if (error_no >= 0 && error_no < sys_nerr)
+    return sys_errlist[error_no];
 
   for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
     if (_wsa_errlist[i].errnum == error_no)
@@ -2562,12 +2684,12 @@ sys_strerror(int error_no)
 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
 #endif
 
+int socket_to_fd (SOCKET s);
+
 int
 sys_socket(int af, int type, int protocol)
 {
-  int fd;
-  long s;
-  child_process * cp;
+  SOCKET s;
 
   if (winsock_lib == NULL)
     {
@@ -2578,105 +2700,114 @@ sys_socket(int af, int type, int protocol)
   check_errno ();
 
   /* call the real socket function */
-  s = (long) pfn_socket (af, type, protocol);
+  s = pfn_socket (af, type, protocol);
   
   if (s != INVALID_SOCKET)
-    {
-      /* Although under NT 3.5 _open_osfhandle will accept a socket
-        handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
-        that does not work under NT 3.1.  However, we can get the same
-        effect by using a backdoor function to replace an existing
-        descriptor handle with the one we want. */
+    return socket_to_fd (s);
 
-      /* allocate a file descriptor (with appropriate flags) */
-      fd = _open ("NUL:", _O_RDWR);
-      if (fd >= 0)
-        {
+  set_errno ();
+  return -1;
+}
+
+/* Convert a SOCKET to a file descriptor.  */
+int
+socket_to_fd (SOCKET s)
+{
+  int fd;
+  child_process * cp;
+
+  /* Although under NT 3.5 _open_osfhandle will accept a socket
+     handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
+     that does not work under NT 3.1.  However, we can get the same
+     effect by using a backdoor function to replace an existing
+     descriptor handle with the one we want. */
+
+  /* allocate a file descriptor (with appropriate flags) */
+  fd = _open ("NUL:", _O_RDWR);
+  if (fd >= 0)
+    {
 #ifdef SOCK_REPLACE_HANDLE
-         /* now replace handle to NUL with our socket handle */
-         CloseHandle ((HANDLE) _get_osfhandle (fd));
-         _free_osfhnd (fd);
-         _set_osfhnd (fd, s);
-         /* setmode (fd, _O_BINARY); */
+      /* now replace handle to NUL with our socket handle */
+      CloseHandle ((HANDLE) _get_osfhandle (fd));
+      _free_osfhnd (fd);
+      _set_osfhnd (fd, s);
+      /* setmode (fd, _O_BINARY); */
 #else
-         /* Make a non-inheritable copy of the socket handle.  Note
-             that it is possible that sockets aren't actually kernel
-             handles, which appears to be the case on Windows 9x when
-             the MS Proxy winsock client is installed.  */
+      /* Make a non-inheritable copy of the socket handle.  Note
+        that it is possible that sockets aren't actually kernel
+        handles, which appears to be the case on Windows 9x when
+        the MS Proxy winsock client is installed.  */
+      {
+       /* Apparently there is a bug in NT 3.51 with some service
+          packs, which prevents using DuplicateHandle to make a
+          socket handle non-inheritable (causes WSACleanup to
+          hang).  The work-around is to use SetHandleInformation
+          instead if it is available and implemented. */
+       if (pfn_SetHandleInformation)
          {
-           /* Apparently there is a bug in NT 3.51 with some service
-              packs, which prevents using DuplicateHandle to make a
-              socket handle non-inheritable (causes WSACleanup to
-              hang).  The work-around is to use SetHandleInformation
-              instead if it is available and implemented. */
-           if (pfn_SetHandleInformation)
-             {
-               pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
-             }
-           else
+           pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
+         }
+       else
+         {
+           HANDLE parent = GetCurrentProcess ();
+           HANDLE new_s = INVALID_HANDLE_VALUE;
+
+           if (DuplicateHandle (parent,
+                                (HANDLE) s,
+                                parent,
+                                &new_s,
+                                0,
+                                FALSE,
+                                DUPLICATE_SAME_ACCESS))
              {
-               HANDLE parent = GetCurrentProcess ();
-               HANDLE new_s = INVALID_HANDLE_VALUE;
-
-               if (DuplicateHandle (parent,
-                                    (HANDLE) s,
-                                    parent,
-                                    &new_s,
-                                    0,
-                                    FALSE,
-                                    DUPLICATE_SAME_ACCESS))
+               /* It is possible that DuplicateHandle succeeds even
+                  though the socket wasn't really a kernel handle,
+                  because a real handle has the same value.  So
+                  test whether the new handle really is a socket.  */
+               long nonblocking = 0;
+               if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
                  {
-                   /* It is possible that DuplicateHandle succeeds even
-                       though the socket wasn't really a kernel handle,
-                       because a real handle has the same value.  So
-                       test whether the new handle really is a socket.  */
-                   long nonblocking = 0;
-                   if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
-                     {
-                       pfn_closesocket (s);
-                       s = (SOCKET) new_s;
-                     }
-                   else
-                     {
-                       CloseHandle (new_s);
-                     }
-                 } 
-             }
+                   pfn_closesocket (s);
+                   s = (SOCKET) new_s;
+                 }
+               else
+                 {
+                   CloseHandle (new_s);
+                 }
+             } 
          }
-         fd_info[fd].hnd = (HANDLE) s;
+      }
+      fd_info[fd].hnd = (HANDLE) s;
 #endif
 
-         /* set our own internal flags */
-         fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
-
-         cp = new_child ();
-         if (cp)
-           {
-             cp->fd = fd;
-             cp->status = STATUS_READ_ACKNOWLEDGED;
-
-             /* attach child_process to fd_info */
-             if (fd_info[ fd ].cp != NULL)
-               {
-                 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
-                 abort ();
-               }
+      /* set our own internal flags */
+      fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
 
-             fd_info[ fd ].cp = cp;
+      cp = new_child ();
+      if (cp)
+       {
+         cp->fd = fd;
+         cp->status = STATUS_READ_ACKNOWLEDGED;
 
-             /* success! */
-             winsock_inuse++;  /* count open sockets */
-             return fd;
+         /* attach child_process to fd_info */
+         if (fd_info[ fd ].cp != NULL)
+           {
+             DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
+             abort ();
            }
 
-         /* clean up */
-         _close (fd);
+         fd_info[ fd ].cp = cp;
+
+         /* success! */
+         winsock_inuse++;      /* count open sockets */
+         return fd;
        }
-      pfn_closesocket (s);
-      h_errno = EMFILE;
-    }
-  set_errno ();
 
+      /* clean up */
+      _close (fd);
+    }
+  pfn_closesocket (s);
+  h_errno = EMFILE;
   return -1;
 }
 
@@ -2752,7 +2883,7 @@ sys_gethostname (char * name, int namelen)
     return pfn_gethostname (name, namelen);
 
   if (namelen > MAX_COMPUTERNAME_LENGTH)
-    return !GetComputerName (name, &namelen);
+    return !GetComputerName (name, (DWORD *)&namelen);
 
   h_errno = EFAULT;
   return SOCKET_ERROR;
@@ -2797,8 +2928,6 @@ sys_getservbyname(const char * name, const char * proto)
 int
 sys_shutdown (int s, int how)
 {
-  int rc;
-
   if (winsock_lib == NULL)
     {
       h_errno = ENETDOWN;
@@ -2817,6 +2946,137 @@ sys_shutdown (int s, int how)
   return SOCKET_ERROR;
 }
 
+int
+sys_setsockopt (int s, int level, int optname, const char * optval, int optlen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
+                              optval, optlen);
+      if (rc == SOCKET_ERROR)
+       set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;      
+}
+
+int
+sys_listen (int s, int backlog)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_listen (SOCK_HANDLE (s), backlog);
+      if (rc == SOCKET_ERROR)
+       set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;      
+}
+
+int
+sys_getsockname (int s, struct sockaddr * name, int * namelen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
+      if (rc == SOCKET_ERROR)
+       set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;      
+}
+
+int
+sys_accept (int s, struct sockaddr * addr, int * addrlen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return -1;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
+      if (t != INVALID_SOCKET)
+       return socket_to_fd (t);
+
+      set_errno ();
+      return -1;
+    }
+  h_errno = ENOTSOCK;
+  return -1;
+}
+
+int
+sys_recvfrom (int s, char * buf, int len, int flags,
+         struct sockaddr * from, int * fromlen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
+      if (rc == SOCKET_ERROR)
+       set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;
+}
+
+int
+sys_sendto (int s, const char * buf, int len, int flags,
+           const struct sockaddr * to, int tolen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
+      if (rc == SOCKET_ERROR)
+       set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;
+}
+
 #endif /* HAVE_SOCKETS */
 
 
@@ -2927,7 +3187,6 @@ sys_pipe (int * phandles)
 {
   int rc;
   unsigned flags;
-  child_process * cp;
 
   /* make pipe handles non-inheritable; when we spawn a child, we
      replace the relevant handle with an inheritable one.  Also put
@@ -3251,7 +3510,7 @@ check_windows_init_file ()
       objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
       full_load_path = Fappend (2, objs);
       init_file = build_string ("term/w32-win");
-      fd = openp (full_load_path, init_file, ".el:.elc", NULL, 0);
+      fd = openp (full_load_path, init_file, Vload_suffixes, NULL, 0);
       if (fd < 0) 
        {
          Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
@@ -3279,7 +3538,7 @@ check_windows_init_file ()
        }
       else
        {
-         close (fd);
+         _close (fd);
        }
     }
 }
@@ -3389,6 +3648,9 @@ init_ntproc ()
 
       (*drive)++;
     }
+
+    /* Reset the volume info cache.  */
+    volume_cache = NULL;
   }
   
   /* Check to see if Emacs has been installed correctly.  */