Remove dependency from 'close' module to -lws2_32 on native Windows.
authorBruno Haible <bruno@clisp.org>
Mon, 23 Mar 2009 22:52:01 +0000 (23:52 +0100)
committerBruno Haible <bruno@clisp.org>
Mon, 23 Mar 2009 22:52:01 +0000 (23:52 +0100)
12 files changed:
ChangeLog
NEWS
lib/close-hook.c [new file with mode: 0644]
lib/close-hook.h [new file with mode: 0644]
lib/close.c
lib/sockets.c
lib/unistd.in.h
m4/close.m4
modules/close
modules/close-hook [new file with mode: 0644]
modules/sockets
modules/sys_socket

index f9fbeb1..0ba878b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2009-03-20  Bruno Haible  <bruno@clisp.org>
+
+       Remove dependency from 'close' module to -lws2_32 on native Windows.
+       * lib/close-hook.h: New file.
+       * lib/close-hook.c: New file.
+       * lib/close.c: Include close-hook.h. Don't include <sys/socket.h>,
+       w32sock.h.
+       (_gl_close_fd_maybe_socket): Remove function.
+       (rpl_close): Invoke execute_all_close_hooks instead of
+       _gl_close_fd_maybe_socket.
+       * lib/sockets.c: Include close-hook.h, w32sock.h.
+       (close_fd_maybe_socket): New function, essentially from lib/close.c.
+       (close_sockets_hook): New variable.
+       (gl_sockets_startup): Register close_fd_maybe_socket as a hook.
+       (gl_sockets_cleanup): Unregister it.
+       * lib/unistd.in.h (HAVE__GL_CLOSE_FD_MAYBE_SOCKET): Remove macro.
+       * m4/close.m4 (gl_REPLACE_CLOSE): Undo 2009-02-05 change.
+       * modules/close-hook: New file.
+       * modules/close (Files): Remove lib/w32sock.h.
+       (Depends-on): Add close-hook.
+       (Link): Remove section.
+       * modules/sockets (Files): Add lib/w32sock.h.
+       (Depends-on): Add close-hook.
+       * modules/sys_socket (configure.ac): Remove gl_MODULE_INDICATOR
+       invocation.
+       * NEWS: Mention that LIB_CLOSE is gone.
+
 2009-03-23  Eric Blake  <ebb9@byu.net>
 
        signal-tests: test previous patch
diff --git a/NEWS b/NEWS
index 17e241f..b975d02 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2009-03-20  close           The substituted variable LIB_CLOSE is removed.
+
 2009-03-05  filevercmp      Move hidden files up in ordering.
 
 2009-01-22  c-strtod        This function no longer calls xalloc_die(). If
diff --git a/lib/close-hook.c b/lib/close-hook.c
new file mode 100644 (file)
index 0000000..afe8e56
--- /dev/null
@@ -0,0 +1,91 @@
+/* Hook for making the close() function extensible.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "close-hook.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#undef close
+
+
+/* Currently, this entire code is only needed for the handling of sockets
+   on native Windows platforms.  */
+#if WINDOWS_SOCKETS
+
+/* The first and last link in the doubly linked list.
+   Initially the list is empty.  */
+static struct close_hook anchor = { &anchor, &anchor, NULL };
+
+int
+execute_close_hooks (int fd, const struct close_hook *remaining_list)
+{
+  if (remaining_list == &anchor)
+    /* End of list reached.  */
+    return close (fd);
+  else
+    return remaining_list->private_fn (fd, remaining_list->private_next);
+}
+
+int
+execute_all_close_hooks (int fd)
+{
+  return execute_close_hooks (fd, anchor.private_next);
+}
+
+void
+register_close_hook (close_hook_fn hook, struct close_hook *link)
+{
+  if (link->private_next == NULL && link->private_prev == NULL)
+    {
+      /* Add the link to the doubly linked list.  */
+      link->private_next = anchor.private_next;
+      link->private_prev = &anchor;
+      link->private_fn = hook;
+      anchor.private_next->private_prev = link;
+      anchor.private_next = link;
+    }
+  else
+    {
+      /* The link is already in use.  */
+      if (link->private_fn != hook)
+       abort ();
+    }
+}
+
+void
+unregister_close_hook (struct close_hook *link)
+{
+  struct close_hook *next = link->private_next;
+  struct close_hook *prev = link->private_prev;
+
+  if (next != NULL && prev != NULL)
+    {
+      /* The link is in use.  Remove it from the doubly linked list.  */
+      prev->private_next = next;
+      next->private_prev = prev;
+      /* Clear the link, to mark it unused.  */
+      link->private_next = NULL;
+      link->private_prev = NULL;
+      link->private_fn = NULL;
+    }
+}
+
+#endif
diff --git a/lib/close-hook.h b/lib/close-hook.h
new file mode 100644 (file)
index 0000000..7369be1
--- /dev/null
@@ -0,0 +1,72 @@
+/* Hook for making the close() function extensible.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifndef CLOSE_HOOK_H
+#define CLOSE_HOOK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Currently, this entire code is only needed for the handling of sockets
+   on native Windows platforms.  */
+#if WINDOWS_SOCKETS
+
+
+/* An element of the list of close hooks.
+   The fields of this structure are considered private.  */
+struct close_hook
+{
+  /* Doubly linked list.  */
+  struct close_hook *private_next;
+  struct close_hook *private_prev;
+  /* Function that treats the types of FD that it knows about and calls
+     execute_close_hooks (FD, REMAINING_LIST) as a fallback.  */
+  int (*private_fn) (int fd, const struct close_hook *remaining_list);
+};
+
+/* This type of function closes FD, applying special knowledge for the FD
+   types it knows about, and calls execute_close_hooks (FD, REMAINING_LIST)
+   for the other FD types.  */
+typedef int (*close_hook_fn) (int fd, const struct close_hook *remaining_list);
+
+/* Execute the close hooks in REMAINING_LIST.
+   Return 0 or -1, like close() would do.  */
+extern int execute_close_hooks (int fd, const struct close_hook *remaining_list);
+
+/* Execute all close hooks.
+   Return 0 or -1, like close() would do.  */
+extern int execute_all_close_hooks (int fd);
+
+/* Add a function to the list of close hooks.
+   The LINK variable points to a piece of memory which is guaranteed to be
+   accessible until the corresponding call to unregister_close_hook.  */
+extern void register_close_hook (close_hook_fn hook, struct close_hook *link);
+
+/* Removes a function from the list of close hooks.  */
+extern void unregister_close_hook (struct close_hook *link);
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CLOSE_HOOK_H */
index 74a7adf..0e56dcb 100644 (file)
@@ -1,5 +1,5 @@
 /* close replacement.
-   Copyright (C) 2008 Free Software Foundation, Inc.
+   Copyright (C) 2008-2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 /* Specification.  */
 #include <unistd.h>
 
-#if GNULIB_SYS_SOCKET
-# define WIN32_LEAN_AND_MEAN
-# include <sys/socket.h>
-#endif
-
-#if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
-
-/* Get set_winsock_errno, FD_TO_SOCKET etc. */
-#include "w32sock.h"
-
-static int
-_gl_close_fd_maybe_socket (int fd)
-{
-  SOCKET sock = FD_TO_SOCKET (fd);
-  WSANETWORKEVENTS ev;
-
-  ev.lNetworkEvents = 0xDEADBEEF;
-  WSAEnumNetworkEvents (sock, NULL, &ev);
-  if (ev.lNetworkEvents != 0xDEADBEEF)
-    {
-      /* FIXME: other applications, like squid, use an undocumented
-        _free_osfhnd free function.  But this is not enough: The 'osfile'
-        flags for fd also needs to be cleared, but it is hard to access it.
-        Instead, here we just close twice the file descriptor.  */
-      if (closesocket (sock))
-       {
-         set_winsock_errno ();
-         return -1;
-       }
-      else
-       {
-         /* This call frees the file descriptor and does a
-            CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails.  */
-         _close (fd);
-         return 0;
-       }
-    }
-  else
-    return _close (fd);
-}
-#endif
+#include "close-hook.h"
 
 /* Override close() to call into other gnulib modules.  */
 
@@ -67,8 +27,8 @@ int
 rpl_close (int fd)
 #undef close
 {
-#if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
-  int retval = _gl_close_fd_maybe_socket (fd);
+#if WINDOWS_SOCKETS
+  int retval = execute_all_close_hooks (fd);
 #else
   int retval = close (fd);
 #endif
index cbec12d..9d5c547 100644 (file)
 /* Specification.  */
 #include "sockets.h"
 
+#if WINDOWS_SOCKETS
+
 /* This includes winsock2.h on MinGW. */
 #include <sys/socket.h>
 
+#include "close-hook.h"
+
+/* Get set_winsock_errno, FD_TO_SOCKET etc. */
+#include "w32sock.h"
+
+static int
+close_fd_maybe_socket (int fd, const struct close_hook *remaining_list)
+{
+  SOCKET sock;
+  WSANETWORKEVENTS ev;
+
+  /* Test whether fd refers to a socket.  */
+  sock = FD_TO_SOCKET (fd);
+  ev.lNetworkEvents = 0xDEADBEEF;
+  WSAEnumNetworkEvents (sock, NULL, &ev);
+  if (ev.lNetworkEvents != 0xDEADBEEF)
+    {
+      /* fd refers to a socket.  */
+      /* FIXME: other applications, like squid, use an undocumented
+        _free_osfhnd free function.  But this is not enough: The 'osfile'
+        flags for fd also needs to be cleared, but it is hard to access it.
+        Instead, here we just close twice the file descriptor.  */
+      if (closesocket (sock))
+       {
+         set_winsock_errno ();
+         return -1;
+       }
+      else
+       {
+         /* This call frees the file descriptor and does a
+            CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails.  */
+         _close (fd);
+         return 0;
+       }
+    }
+  else
+    /* Some other type of file descriptor.  */
+    return execute_close_hooks (fd, remaining_list);
+}
+
+static struct close_hook close_sockets_hook;
+
+#endif
+
 int
 gl_sockets_startup (int version)
 {
@@ -38,6 +84,8 @@ gl_sockets_startup (int version)
 
   if (data.wVersion < version)
     return 2;
+
+  register_close_hook (close_fd_maybe_socket, &close_sockets_hook);
 #endif
 
   return 0;
@@ -49,6 +97,8 @@ gl_sockets_cleanup (void)
 #if WINDOWS_SOCKETS
   int err;
 
+  unregister_close_hook (&close_sockets_hook);
+
   err = WSACleanup ();
   if (err != 0)
     return 1;
index d8276b1..cd3a60b 100644 (file)
@@ -131,10 +131,6 @@ extern int chown (const char *file, uid_t uid, gid_t gid);
 
 
 #if @GNULIB_CLOSE@
-# if @UNISTD_H_HAVE_WINSOCK2_H@
-/* Need a gnulib internal function.  */
-#  define HAVE__GL_CLOSE_FD_MAYBE_SOCKET 1
-# endif
 # if @REPLACE_CLOSE@
 /* Automatically included by modules that need a replacement for close.  */
 #  undef close
index 29d3abd..b1189f5 100644 (file)
@@ -1,5 +1,5 @@
-# close.m4 serial 2
-dnl Copyright (C) 2008 Free Software Foundation, Inc.
+# close.m4 serial 3
+dnl Copyright (C) 2008-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -22,6 +22,4 @@ AC_DEFUN([gl_REPLACE_CLOSE],
   fi
   REPLACE_CLOSE=1
   gl_REPLACE_FCLOSE
-  LIB_CLOSE="-lws2_32"
-  AC_SUBST([LIB_CLOSE])
 ])
index 138be1b..e294292 100644 (file)
@@ -3,11 +3,11 @@ close() function: close a file or socket.
 
 Files:
 lib/close.c
-lib/w32sock.h
 m4/close.m4
 
 Depends-on:
 unistd
+close-hook
 fclose
 
 configure.ac:
@@ -19,9 +19,6 @@ Makefile.am:
 Include:
 <unistd.h>
 
-Link:
-$(LIB_CLOSE)
-
 License:
 LGPLv2+
 
diff --git a/modules/close-hook b/modules/close-hook
new file mode 100644 (file)
index 0000000..ae32ad0
--- /dev/null
@@ -0,0 +1,23 @@
+Description:
+Hook for making close() extensible.
+
+Files:
+lib/close-hook.h
+lib/close-hook.c
+
+Depends-on:
+unistd
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += close-hook.c
+
+Include:
+"close-hook.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
index 8cce37e..9e03ac6 100644 (file)
@@ -4,10 +4,12 @@ General facilities for using sockets
 Files:
 lib/sockets.c
 lib/sockets.h
+lib/w32sock.h
 m4/sockets.m4
 
 Depends-on:
 sys_socket
+close-hook
 
 configure.ac:
 gl_SOCKETS
index 98b4429..011fe69 100644 (file)
@@ -13,7 +13,6 @@ errno
 
 configure.ac:
 gl_HEADER_SYS_SOCKET
-gl_MODULE_INDICATOR([sys_socket])
 AC_PROG_MKDIR_P
 
 Makefile.am: