(pfn_WSACreateEvent, pfn_WSACloseEvent): New func ptrs.
[bpt/emacs.git] / src / w32.c
index 25283c3..d01a102 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,5 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004,
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -949,11 +950,11 @@ init_environment (char ** argv)
     struct stat ignored;
     char default_home[MAX_PATH];
 
-    static struct env_entry
+    static const struct env_entry
     {
       char * name;
       char * def_value;
-    } env_vars[] =
+    } dflt_envvars[] =
     {
       {"HOME", "C:/"},
       {"PRELOAD_WINSOCK", NULL},
@@ -970,6 +971,17 @@ init_environment (char ** argv)
       {"LANG", NULL},
     };
 
+#define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
+
+    /* We need to copy dflt_envvars[] and work on the copy because we
+       don't want the dumped Emacs to inherit the values of
+       environment variables we saw during dumping (which could be on
+       a different system).  The defaults above must be left intact.  */
+    struct env_entry env_vars[N_ENV_VARS];
+
+    for (i = 0; i < N_ENV_VARS; i++)
+      env_vars[i] = dflt_envvars[i];
+
     /* For backwards compatibility, check if a .emacs file exists in C:/
        If not, then we can try to default to the appdata directory under the
        user's profile, which is more likely to be writable.   */
@@ -1004,7 +1016,7 @@ init_environment (char ** argv)
                      LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
                      locale_name, sizeof (locale_name)))
     {
-      for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
+      for (i = 0; i < N_ENV_VARS; i++)
         {
           if (strcmp (env_vars[i].name, "LANG") == 0)
             {
@@ -1068,7 +1080,7 @@ init_environment (char ** argv)
        }
     }
 
-    for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
+    for (i = 0; i < N_ENV_VARS; i++)
       {
        if (!getenv (env_vars[i].name))
          {
@@ -1083,20 +1095,17 @@ init_environment (char ** argv)
 
            if (lpval)
              {
-               if (dwType == REG_EXPAND_SZ)
-                 {
-                   char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
+               char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
 
-                   ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
-                   _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name, buf1);
-                   _putenv (strdup (buf2));
-                 }
+               if (dwType == REG_EXPAND_SZ)
+                 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
                else if (dwType == REG_SZ)
+                 strcpy (buf1, lpval);
+               if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
                  {
-                   char buf[SET_ENV_BUF_SIZE];
-
-                   _snprintf (buf, sizeof(buf)-1, "%s=%s", env_vars[i].name, lpval);
-                   _putenv (strdup (buf));
+                   _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
+                              buf1);
+                   _putenv (strdup (buf2));
                  }
 
                if (!dont_free)
@@ -2691,6 +2700,9 @@ utime (const char *name, struct utimbuf *times)
 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
 void (PASCAL *pfn_WSASetLastError) (int iError);
 int (PASCAL *pfn_WSAGetLastError) (void);
+int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
+HANDLE (PASCAL *pfn_WSACreateEvent) (void);
+int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
 int (PASCAL *pfn_socket) (int af, int type, int protocol);
 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
@@ -2760,7 +2772,7 @@ init_winsock (int load_now)
     = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
                               "SetHandleInformation");
 
-  winsock_lib = LoadLibrary ("wsock32.dll");
+  winsock_lib = LoadLibrary ("Ws2_32.dll");
 
   if (winsock_lib != NULL)
     {
@@ -2773,6 +2785,9 @@ init_winsock (int load_now)
       LOAD_PROC( WSAStartup );
       LOAD_PROC( WSASetLastError );
       LOAD_PROC( WSAGetLastError );
+      LOAD_PROC( WSAEventSelect );
+      LOAD_PROC( WSACreateEvent );
+      LOAD_PROC( WSACloseEvent );
       LOAD_PROC( socket );
       LOAD_PROC( bind );
       LOAD_PROC( connect );
@@ -3286,6 +3301,8 @@ sys_listen (int s, int backlog)
       int rc = pfn_listen (SOCK_HANDLE (s), backlog);
       if (rc == SOCKET_ERROR)
        set_errno ();
+      else
+       fd_info[s].flags |= FILE_LISTEN;
       return rc;
     }
   h_errno = ENOTSOCK;
@@ -3323,14 +3340,18 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
     }
 
   check_errno ();
-  if (fd_info[s].flags & FILE_SOCKET)
+  if (fd_info[s].flags & FILE_LISTEN)
     {
       SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
-      if (t != INVALID_SOCKET)
-       return socket_to_fd (t);
+      int fd = -1;
+      if (t == INVALID_SOCKET)
+       set_errno ();
+      else
+       fd = socket_to_fd (t);
 
-      set_errno ();
-      return -1;
+      fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
+      ResetEvent (fd_info[s].cp->char_avail);
+      return fd;
     }
   h_errno = ENOTSOCK;
   return -1;
@@ -3425,13 +3446,13 @@ sys_close (int fd)
 {
   int rc;
 
-  if (fd < 0 || fd >= MAXDESC)
+  if (fd < 0)
     {
       errno = EBADF;
       return -1;
     }
 
-  if (fd_info[fd].cp)
+  if (fd < MAXDESC && fd_info[fd].cp)
     {
       child_process * cp = fd_info[fd].cp;
 
@@ -3473,7 +3494,7 @@ sys_close (int fd)
      because socket handles are fully fledged kernel handles. */
   rc = _close (fd);
 
-  if (rc == 0)
+  if (rc == 0 && fd < MAXDESC)
     fd_info[fd].flags = 0;
 
   return rc;
@@ -3485,7 +3506,7 @@ sys_dup (int fd)
   int new_fd;
 
   new_fd = _dup (fd);
-  if (new_fd >= 0)
+  if (new_fd >= 0 && new_fd < MAXDESC)
     {
       /* duplicate our internal info as well */
       fd_info[new_fd] = fd_info[fd];
@@ -3632,6 +3653,36 @@ _sys_read_ahead (int fd)
   return cp->status;
 }
 
+int _sys_wait_accept (int fd)
+{
+  HANDLE hEv;
+  child_process * cp;
+  int rc;
+
+  if (fd < 0 || fd >= MAXDESC)
+    return STATUS_READ_ERROR;
+
+  cp = fd_info[fd].cp;
+
+  if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
+    return STATUS_READ_ERROR;
+
+  cp->status = STATUS_READ_FAILED;
+
+  hEv = pfn_WSACreateEvent ();
+  rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
+  if (rc != SOCKET_ERROR)
+    {
+      rc = WaitForSingleObject (hEv, INFINITE);
+      pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
+      pfn_WSACloseEvent (hEv);
+      if (rc == WAIT_OBJECT_0)
+       cp->status = STATUS_READ_SUCCEEDED;
+    }
+
+  return cp->status;
+}
+
 int
 sys_read (int fd, char * buffer, unsigned int count)
 {
@@ -3640,13 +3691,13 @@ sys_read (int fd, char * buffer, unsigned int count)
   DWORD waiting;
   char * orig_buffer = buffer;
 
-  if (fd < 0 || fd >= MAXDESC)
+  if (fd < 0)
     {
       errno = EBADF;
       return -1;
     }
 
-  if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
+  if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
     {
       child_process *cp = fd_info[fd].cp;
 
@@ -3784,13 +3835,13 @@ sys_write (int fd, const void * buffer, unsigned int count)
 {
   int nchars;
 
-  if (fd < 0 || fd >= MAXDESC)
+  if (fd < 0)
     {
       errno = EBADF;
       return -1;
     }
 
-  if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
+  if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
     {
       if ((fd_info[fd].flags & FILE_WRITE) == 0)
        {
@@ -3832,7 +3883,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
     }
 
 #ifdef HAVE_SOCKETS
-  if (fd_info[fd].flags & FILE_SOCKET)
+  if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
     {
       unsigned long nblock = 0;
       if (winsock_lib == NULL) abort ();
@@ -3887,13 +3938,15 @@ 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, Vload_suffixes, NULL, Qnil);
+      fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
       if (fd < 0)
        {
          Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
          char *init_file_name = SDATA (init_file);
          char *load_path = SDATA (load_path_print);
-         char *buffer = alloca (1024);
+         char *buffer = alloca (1024
+                                + strlen (init_file_name)
+                                + strlen (load_path));
 
          sprintf (buffer,
                   "The Emacs Windows initialization file \"%s.el\" "