changeset 15357:6686192ea2b3

(init_environment): Read PRELOAD_WINSOCK from registry if not set in environment. (winsock_inuse) [HAVE_SOCKETS]: New variable. (have_winsock) [HAVE_SOCKETS]: Obsolete variable removed. (term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there are no active sockets still open, and if the cleanup function succeeds. Return TRUE if winsock is unloaded. (init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded, and return TRUE if winsock support is available. Unload winsock immediately if new parameter load_now is false. Check that WSAStartup supports the winsock version we requested. (set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons, sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname, sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]: Check winsock_lib instead of have_winsock to determine if winsock support is available. (sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use. (init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup if PRELOAD_WINSOCK is set in environment (or registry).
author Richard M. Stallman <rms@gnu.org>
date Sat, 08 Jun 1996 00:22:50 +0000
parents 1a917c5d944c
children 91b8056dcd35
files src/w32.c
diffstat 1 files changed, 74 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32.c	Sat Jun 08 00:15:00 1996 +0000
+++ b/src/w32.c	Sat Jun 08 00:22:50 1996 +0000
@@ -584,6 +584,7 @@
     static char * env_vars[] = 
     {
       "HOME",
+      "PRELOAD_WINSOCK",
       "emacs_dir",
       "EMACSLOADPATH",
       "SHELL",
@@ -1389,25 +1390,35 @@
 #define HANDLE_FLAG_INHERIT	1
 #endif
 
-static int have_winsock;
-static HANDLE winsock_lib;
+HANDLE winsock_lib;
+static int winsock_inuse;
 
-static void
+BOOL
 term_winsock (void)
 {
-  if (have_winsock)
+  if (winsock_lib != NULL && winsock_inuse == 0)
     {
-      pfn_WSACleanup ();
-      FreeLibrary (winsock_lib);
+      /* Not sure what would cause WSAENETDOWN, or even if it can happen
+	 after WSAStartup returns successfully, but it seems reasonable
+	 to allow unloading winsock anyway in that case. */
+      if (pfn_WSACleanup () == 0 ||
+	  pfn_WSAGetLastError () == WSAENETDOWN)
+	{
+	  if (FreeLibrary (winsock_lib))
+	  winsock_lib = NULL;
+	  return TRUE;
+	}
     }
+  return FALSE;
 }
 
-static void
-init_winsock ()
+BOOL
+init_winsock (int load_now)
 {
   WSADATA  winsockData;
 
-  have_winsock = FALSE;
+  if (winsock_lib != NULL)
+    return TRUE;
 
   pfn_SetHandleInformation = NULL;
   pfn_SetHandleInformation
@@ -1443,16 +1454,36 @@
       LOAD_PROC( getservbyname );
       LOAD_PROC( WSACleanup );
 
+#undef LOAD_PROC
+
       /* specify version 1.1 of winsock */
       if (pfn_WSAStartup (0x101, &winsockData) == 0)
         {
-	  have_winsock = TRUE;
-	  return;
+	  if (winsockData.wVersion != 0x101)
+	    goto fail;
+
+	  if (!load_now)
+	    {
+	      /* Report that winsock exists and is usable, but leave
+		 socket functions disabled.  I am assuming that calling
+		 WSAStartup does not require any network interaction,
+		 and in particular does not cause or require a dial-up
+		 connection to be established. */
+
+	      pfn_WSACleanup ();
+	      FreeLibrary (winsock_lib);
+	      winsock_lib = NULL;
+	    }
+	  winsock_inuse = 0;
+	  return TRUE;
 	}
 
     fail:
       FreeLibrary (winsock_lib);
+      winsock_lib = NULL;
     }
+
+  return FALSE;
 }
 
 
@@ -1463,7 +1494,7 @@
    are already in <sys/socket.h> */
 static void set_errno ()
 {
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     h_errno = EINVAL;
   else
     h_errno = pfn_WSAGetLastError ();
@@ -1484,7 +1515,7 @@
 
 static void check_errno ()
 {
-  if (h_errno == 0 && have_winsock)
+  if (h_errno == 0 && winsock_lib != NULL)
     pfn_WSASetLastError (0);
 }
 
@@ -1507,7 +1538,7 @@
   long s;
   child_process * cp;
 
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     {
       h_errno = ENETDOWN;
       return INVALID_SOCKET;
@@ -1587,6 +1618,7 @@
 	      fd_info[ fd ].cp = cp;
 
 	      /* success! */
+	      winsock_inuse++;	/* count open sockets */
 	      return fd;
 	    }
 
@@ -1605,7 +1637,7 @@
 int
 sys_bind (int s, const struct sockaddr * addr, int namelen)
 {
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     {
       h_errno = ENOTSOCK;
       return SOCKET_ERROR;
@@ -1627,7 +1659,7 @@
 int
 sys_connect (int s, const struct sockaddr * name, int namelen)
 {
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     {
       h_errno = ENOTSOCK;
       return SOCKET_ERROR;
@@ -1648,28 +1680,28 @@
 u_short
 sys_htons (u_short hostshort)
 {
-  return (have_winsock) ?
+  return (winsock_lib != NULL) ?
     pfn_htons (hostshort) : hostshort;
 }
 
 u_short
 sys_ntohs (u_short netshort)
 {
-  return (have_winsock) ?
+  return (winsock_lib != NULL) ?
     pfn_ntohs (netshort) : netshort;
 }
 
 unsigned long
 sys_inet_addr (const char * cp)
 {
-  return (have_winsock) ?
+  return (winsock_lib != NULL) ?
     pfn_inet_addr (cp) : INADDR_NONE;
 }
 
 int
 sys_gethostname (char * name, int namelen)
 {
-  if (have_winsock)
+  if (winsock_lib != NULL)
     return pfn_gethostname (name, namelen);
 
   if (namelen > MAX_COMPUTERNAME_LENGTH)
@@ -1684,7 +1716,7 @@
 {
   struct hostent * host;
 
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     {
       h_errno = ENETDOWN;
       return NULL;
@@ -1702,7 +1734,7 @@
 {
   struct servent * serv;
 
-  if (!have_winsock)
+  if (winsock_lib == NULL)
     {
       h_errno = ENETDOWN;
       return NULL;
@@ -1751,13 +1783,16 @@
 	    }
 	  if (i == MAXDESC)
 	    {
-#if defined (HAVE_SOCKETS) && !defined (SOCK_REPLACE_HANDLE)
+#ifdef HAVE_SOCKETS
 	      if (fd_info[fd].flags & FILE_SOCKET)
 		{
-		  if (!have_winsock) abort ();
+#ifndef SOCK_REPLACE_HANDLE
+		  if (winsock_lib == NULL) abort ();
 
 		  pfn_shutdown (SOCK_HANDLE (fd), 2);
 		  rc = pfn_closesocket (SOCK_HANDLE (fd));
+#endif
+		  winsock_inuse--; /* count open sockets */
 		}
 #endif
 	      delete_child (cp);
@@ -2010,7 +2045,7 @@
 #ifdef HAVE_SOCKETS
 	  else /* FILE_SOCKET */
 	    {
-	      if (!have_winsock) abort ();
+	      if (winsock_lib == NULL) abort ();
 
 	      /* do the equivalent of a non-blocking read */
 	      pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
@@ -2070,7 +2105,7 @@
 #ifdef HAVE_SOCKETS
   if (fd_info[fd].flags & FILE_SOCKET)
     {
-      if (!have_winsock) abort ();
+      if (winsock_lib == NULL) abort ();
       nchars =  pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
       if (nchars == SOCKET_ERROR)
         {
@@ -2103,8 +2138,19 @@
 init_ntproc ()
 {
 #ifdef HAVE_SOCKETS
-  /* initialise the socket interface if available */
-  init_winsock ();
+  /* Initialise the socket interface now if available and requested by
+     the user by defining PRELOAD_WINSOCK; otherwise loading will be
+     delayed until open-network-stream is called (win32-has-winsock can
+     also be used to dynamically load or reload winsock).
+
+     Conveniently, init_environment is called before us, so
+     PRELOAD_WINSOCK can be set in the registry. */
+
+  /* Always initialize this correctly. */
+  winsock_lib = NULL;
+
+  if (getenv ("PRELOAD_WINSOCK") != NULL)
+    init_winsock (TRUE);
 #endif
 
   /* Initial preparation for subprocess support: replace our standard