static char * env_vars[] =
{
"HOME",
+ "PRELOAD_WINSOCK",
"emacs_dir",
"EMACSLOADPATH",
"SHELL",
#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
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;
}
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 ();
static void check_errno ()
{
- if (h_errno == 0 && have_winsock)
+ if (h_errno == 0 && winsock_lib != NULL)
pfn_WSASetLastError (0);
}
long s;
child_process * cp;
- if (!have_winsock)
+ if (winsock_lib == NULL)
{
h_errno = ENETDOWN;
return INVALID_SOCKET;
fd_info[ fd ].cp = cp;
/* success! */
+ winsock_inuse++; /* count open sockets */
return fd;
}
int
sys_bind (int s, const struct sockaddr * addr, int namelen)
{
- if (!have_winsock)
+ if (winsock_lib == NULL)
{
h_errno = ENOTSOCK;
return SOCKET_ERROR;
int
sys_connect (int s, const struct sockaddr * name, int namelen)
{
- if (!have_winsock)
+ if (winsock_lib == NULL)
{
h_errno = ENOTSOCK;
return SOCKET_ERROR;
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)
{
struct hostent * host;
- if (!have_winsock)
+ if (winsock_lib == NULL)
{
h_errno = ENETDOWN;
return NULL;
{
struct servent * serv;
- if (!have_winsock)
+ if (winsock_lib == NULL)
{
h_errno = ENETDOWN;
return NULL;
}
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);
#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);
#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)
{
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