From 6110d07dee40692d43f2ef8884230e0d53c56548 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Mon, 18 Apr 2011 02:34:47 +0200
Subject: [PATCH] ioctl: Remove link dependency on native Windows.

* lib/fd-hook.h: Renamed from lib/close-hook.h.
(gl_close_fn, gl_ioctl_fn): New types.
(struct fd_hook): Renamed from struct close_hook. Change type of
private_close_fn field. Add private_ioctl_fn field.
(close_hook_fn): Add parameter for primary close method.
(execute_close_hooks, execute_all_close_hooks): Likewise.
(ioctl_hook_fn): New type.
(execute_ioctl_hooks, execute_all_ioctl_hooks): New declarations.
(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
argument.
(unregister_fd_hook): Renamed from unregister_close_hook.
* lib/fd-hook.c: Renamed from lib/close-hook.c.
Don't include <unistd.h>.
(close): Remove undef.
(anchor): Update.
(execute_close_hooks): Add argument for primary close method.
(execute_all_close_hooks): Likewise.
(execute_ioctl_hooks, execute_all_ioctl_hooks): New functions.
(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
argument. Allow each argument to be NULL.
(unregister_fd_hook): Renamed from unregister_close_hook.
* lib/close.c (rpl_close): Pass 'close' function pointer to
execute_all_close_hooks.
* lib/ioctl.c: Include <errno.h>, fd-hook.h.
(primary_ioctl): New function.
(ioctl): Don't call ioctlsocket here. Instead, call
execute_all_ioctl_hooks.
* lib/sockets.c (close_fd_maybe_socket): Add argument for primary
close method.
(ioctl_fd_maybe_socket): New function, with code from lib/ioctl.c.
(fd_sockets_hook): Renamed from close_sockets_hook.
(gl_sockets_startup, gl_sockets_cleanup): Update.
* modules/fd-hook: Renamed from modules/close-hook. Update.
* modules/close (Depends-on): Add fd-hook, remove close-hook.
* modules/sockets (Depends-on): Likewise.
* modules/ioctl (Depends-on): Add fd-hook.
* tests/test-nonblocking.c (main): Use GNULIB_TEST_SOCKET, not
GNULIB_SOCKET.
---
 ChangeLog                       |  42 +++++++++++
 NEWS                            |   3 +
 lib/close-hook.h                |  72 -------------------
 lib/close.c                     |   4 +-
 lib/{close-hook.c => fd-hook.c} |  63 ++++++++++++-----
 lib/fd-hook.h                   | 119 ++++++++++++++++++++++++++++++++
 lib/ioctl.c                     |  43 +++++-------
 lib/sockets.c                   |  43 ++++++++++--
 modules/close                   |   2 +-
 modules/close-hook              |  23 ------
 modules/fd-hook                 |  23 ++++++
 modules/ioctl                   |   1 +
 modules/sockets                 |   2 +-
 tests/test-nonblocking.c        |   4 +-
 14 files changed, 294 insertions(+), 150 deletions(-)
 delete mode 100644 lib/close-hook.h
 rename lib/{close-hook.c => fd-hook.c} (51%)
 create mode 100644 lib/fd-hook.h
 delete mode 100644 modules/close-hook
 create mode 100644 modules/fd-hook

diff --git a/ChangeLog b/ChangeLog
index 48a12610ef..8a267bf7b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2011-04-19  Bruno Haible  <bruno@clisp.org>
+
+	ioctl: Remove link dependency on native Windows.
+	* lib/fd-hook.h: Renamed from lib/close-hook.h.
+	(gl_close_fn, gl_ioctl_fn): New types.
+	(struct fd_hook): Renamed from struct close_hook. Change type of
+	private_close_fn field. Add private_ioctl_fn field.
+	(close_hook_fn): Add parameter for primary close method.
+	(execute_close_hooks, execute_all_close_hooks): Likewise.
+	(ioctl_hook_fn): New type.
+	(execute_ioctl_hooks, execute_all_ioctl_hooks): New declarations.
+	(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
+	argument.
+	(unregister_fd_hook): Renamed from unregister_close_hook.
+	* lib/fd-hook.c: Renamed from lib/close-hook.c.
+	Don't include <unistd.h>.
+	(close): Remove undef.
+	(anchor): Update.
+	(execute_close_hooks): Add argument for primary close method.
+	(execute_all_close_hooks): Likewise.
+	(execute_ioctl_hooks, execute_all_ioctl_hooks): New functions.
+	(register_fd_hook): Renamed from register_close_hook. Add ioctl_hook
+	argument. Allow each argument to be NULL.
+	(unregister_fd_hook): Renamed from unregister_close_hook.
+	* lib/close.c (rpl_close): Pass 'close' function pointer to
+	execute_all_close_hooks.
+	* lib/ioctl.c: Include <errno.h>, fd-hook.h.
+	(primary_ioctl): New function.
+	(ioctl): Don't call ioctlsocket here. Instead, call
+	execute_all_ioctl_hooks.
+	* lib/sockets.c (close_fd_maybe_socket): Add argument for primary
+	close method.
+	(ioctl_fd_maybe_socket): New function, with code from lib/ioctl.c.
+	(fd_sockets_hook): Renamed from close_sockets_hook.
+	(gl_sockets_startup, gl_sockets_cleanup): Update.
+	* modules/fd-hook: Renamed from modules/close-hook. Update.
+	* modules/close (Depends-on): Add fd-hook, remove close-hook.
+	* modules/sockets (Depends-on): Likewise.
+	* modules/ioctl (Depends-on): Add fd-hook.
+	* tests/test-nonblocking.c (main): Use GNULIB_TEST_SOCKET, not
+	GNULIB_SOCKET.
+
 2011-04-19  Bruno Haible  <bruno@clisp.org>
 
 	Move the support of O_NONBLOCK in open() to the 'open' module.
diff --git a/NEWS b/NEWS
index 767d0ab01b..7dd126dac6 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2011-04-19  close-hook      This module has been renamed to 'fd-hook' and
+                            generalized.
+
 2011-03-08  regex-quote     The last argument is no longer an 'int cflags'
                             but instead a pointer to a previously constructed
                             'struct regex_quote_spec'.
diff --git a/lib/close-hook.h b/lib/close-hook.h
deleted file mode 100644
index adcf11c22a..0000000000
--- a/lib/close-hook.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Hook for making the close() function extensible.
-   Copyright (C) 2009-2011 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 */
diff --git a/lib/close.c b/lib/close.c
index 1c06c166f7..2c41c75b8b 100644
--- a/lib/close.c
+++ b/lib/close.c
@@ -19,7 +19,7 @@
 /* Specification.  */
 #include <unistd.h>
 
-#include "close-hook.h"
+#include "fd-hook.h"
 
 /* Override close() to call into other gnulib modules.  */
 
@@ -28,7 +28,7 @@ rpl_close (int fd)
 #undef close
 {
 #if WINDOWS_SOCKETS
-  int retval = execute_all_close_hooks (fd);
+  int retval = execute_all_close_hooks (close, fd);
 #else
   int retval = close (fd);
 #endif
diff --git a/lib/close-hook.c b/lib/fd-hook.c
similarity index 51%
rename from lib/close-hook.c
rename to lib/fd-hook.c
index 0fdf323588..40fbeeb345 100644
--- a/lib/close-hook.c
+++ b/lib/fd-hook.c
@@ -1,4 +1,4 @@
-/* Hook for making the close() function extensible.
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
    Copyright (C) 2009-2011 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2009.
 
@@ -18,13 +18,9 @@
 #include <config.h>
 
 /* Specification.  */
-#include "close-hook.h"
+#include "fd-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.  */
@@ -32,49 +28,77 @@
 
 /* The first and last link in the doubly linked list.
    Initially the list is empty.  */
-static struct close_hook anchor = { &anchor, &anchor, NULL };
+static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
+
+int
+execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
+                     int fd)
+{
+  if (remaining_list == &anchor)
+    /* End of list reached.  */
+    return primary (fd);
+  else
+    return remaining_list->private_close_fn (remaining_list->private_next,
+                                             primary, fd);
+}
 
 int
-execute_close_hooks (int fd, const struct close_hook *remaining_list)
+execute_all_close_hooks (gl_close_fn primary, int fd)
+{
+  return execute_close_hooks (anchor.private_next, primary, fd);
+}
+
+int
+execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
+                     int fd, int request, void *arg)
 {
   if (remaining_list == &anchor)
     /* End of list reached.  */
-    return close (fd);
+    return primary (fd, request, arg);
   else
-    return remaining_list->private_fn (fd, remaining_list->private_next);
+    return remaining_list->private_ioctl_fn (remaining_list->private_next,
+                                             primary, fd, request, arg);
 }
 
 int
-execute_all_close_hooks (int fd)
+execute_all_ioctl_hooks (gl_ioctl_fn primary,
+                         int fd, int request, void *arg)
 {
-  return execute_close_hooks (fd, anchor.private_next);
+  return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
 }
 
 void
-register_close_hook (close_hook_fn hook, struct close_hook *link)
+register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
 {
+  if (close_hook == NULL)
+    close_hook = execute_close_hooks;
+  if (ioctl_hook == NULL)
+    ioctl_hook = execute_ioctl_hooks;
+
   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;
+      link->private_close_fn = close_hook;
+      link->private_ioctl_fn = ioctl_hook;
       anchor.private_next->private_prev = link;
       anchor.private_next = link;
     }
   else
     {
       /* The link is already in use.  */
-      if (link->private_fn != hook)
+      if (link->private_close_fn != close_hook
+          || link->private_ioctl_fn != ioctl_hook)
         abort ();
     }
 }
 
 void
-unregister_close_hook (struct close_hook *link)
+unregister_fd_hook (struct fd_hook *link)
 {
-  struct close_hook *next = link->private_next;
-  struct close_hook *prev = link->private_prev;
+  struct fd_hook *next = link->private_next;
+  struct fd_hook *prev = link->private_prev;
 
   if (next != NULL && prev != NULL)
     {
@@ -84,7 +108,8 @@ unregister_close_hook (struct close_hook *link)
       /* Clear the link, to mark it unused.  */
       link->private_next = NULL;
       link->private_prev = NULL;
-      link->private_fn = NULL;
+      link->private_close_fn = NULL;
+      link->private_ioctl_fn = NULL;
     }
 }
 
diff --git a/lib/fd-hook.h b/lib/fd-hook.h
new file mode 100644
index 0000000000..aab4d913c1
--- /dev/null
+++ b/lib/fd-hook.h
@@ -0,0 +1,119 @@
+/* Hook for making making file descriptor functions close(), ioctl() extensible.
+   Copyright (C) 2009-2011 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 FD_HOOK_H
+#define FD_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
+
+
+/* Type of function that closes FD.  */
+typedef int (*gl_close_fn) (int fd);
+
+/* Type of function that applies a control request to FD.  */
+typedef int (*gl_ioctl_fn) (int fd, int request, void *arg);
+
+/* An element of the list of file descriptor hooks.
+   In CLOS (Common Lisp Object System) speak, it consists of an "around"
+   method for the close() function and an "around" method for the ioctl()
+   function.
+   The fields of this structure are considered private.  */
+struct fd_hook
+{
+  /* Doubly linked list.  */
+  struct fd_hook *private_next;
+  struct fd_hook *private_prev;
+  /* Function that treats the types of FD that it knows about and calls
+     execute_close_hooks (REMAINING_LIST, PRIMARY, FD) as a fallback.  */
+  int (*private_close_fn) (const struct fd_hook *remaining_list,
+                           gl_close_fn primary,
+                           int fd);
+  /* Function that treats the types of FD that it knows about and calls
+     execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG) as a
+     fallback.  */
+  int (*private_ioctl_fn) (const struct fd_hook *remaining_list,
+                           gl_ioctl_fn primary,
+                           int fd, int request, void *arg);
+};
+
+/* This type of function closes FD, applying special knowledge for the FD
+   types it knows about, and calls
+   execute_close_hooks (REMAINING_LIST, PRIMARY, FD)
+   for the other FD types.
+   In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+   and PRIMARY is the "primary" method for close().  */
+typedef int (*close_hook_fn) (const struct fd_hook *remaining_list,
+                              gl_close_fn primary,
+                              int fd);
+
+/* Execute the close hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+   Return 0 or -1, like close() would do.  */
+extern int execute_close_hooks (const struct fd_hook *remaining_list,
+                                gl_close_fn primary,
+                                int fd);
+
+/* Execute all close hooks, with PRIMARY as "primary" method.
+   Return 0 or -1, like close() would do.  */
+extern int execute_all_close_hooks (gl_close_fn primary, int fd);
+
+/* This type of function applies a control request to FD, applying special
+   knowledge for the FD types it knows about, and calls
+   execute_ioctl_hooks (REMAINING_LIST, PRIMARY, FD, REQUEST, ARG)
+   for the other FD types.
+   In CLOS speak, REMAINING_LIST is the remaining list of "around" methods,
+   and PRIMARY is the "primary" method for ioctl().  */
+typedef int (*ioctl_hook_fn) (const struct fd_hook *remaining_list,
+                              gl_ioctl_fn primary,
+                              int fd, int request, void *arg);
+
+/* Execute the ioctl hooks in REMAINING_LIST, with PRIMARY as "primary" method.
+   Return 0 or -1, like ioctl() would do.  */
+extern int execute_ioctl_hooks (const struct fd_hook *remaining_list,
+                                gl_ioctl_fn primary,
+                                int fd, int request, void *arg);
+
+/* Execute all ioctl hooks, with PRIMARY as "primary" method.
+   Return 0 or -1, like ioctl() would do.  */
+extern int execute_all_ioctl_hooks (gl_ioctl_fn primary,
+                                    int fd, int request, void *arg);
+
+/* Add a function pair to the list of file descriptor hooks.
+   CLOSE_HOOK and IOCTL_HOOK may be NULL, indicating no change.
+   The LINK variable points to a piece of memory which is guaranteed to be
+   accessible until the corresponding call to unregister_fd_hook.  */
+extern void register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook,
+                              struct fd_hook *link);
+
+/* Removes a hook from the list of file descriptor hooks.  */
+extern void unregister_fd_hook (struct fd_hook *link);
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FD_HOOK_H */
diff --git a/lib/ioctl.c b/lib/ioctl.c
index 00caf3b187..c6ba989ee5 100644
--- a/lib/ioctl.c
+++ b/lib/ioctl.c
@@ -44,40 +44,35 @@ rpl_ioctl (int fd, int request, ... /* {void *,char *} arg */)
 
 #else /* mingw */
 
-# define WIN32_LEAN_AND_MEAN
-/* Get winsock2.h. */
-# include <sys/socket.h>
+# include <errno.h>
 
-/* Get set_winsock_errno, FD_TO_SOCKET etc. */
-# include "w32sock.h"
+# include "fd-hook.h"
 
-int
-ioctl (int fd, int req, ...)
+static int
+primary_ioctl (int fd, int request, void *arg)
 {
-# if GNULIB_SOCKET
-  void *buf;
-  va_list args;
-  SOCKET sock;
-  int r;
-
-  va_start (args, req);
-  buf = va_arg (args, void *);
-  va_end (args);
-
   /* We don't support FIONBIO on pipes here.  If you want to make pipe
      fds non-blocking, use the gnulib 'nonblocking' module, until
      gnulib implements fcntl F_GETFL / F_SETFL with O_NONBLOCK.  */
 
-  sock = FD_TO_SOCKET (fd);
-  r = ioctlsocket (sock, req, buf);
-  if (r < 0)
-    set_winsock_errno ();
+  errno = ENOSYS;
+  return -1;
+}
+
+int
+ioctl (int fd, int request, ... /* {void *,char *} arg */)
+{
+  void *arg;
+  va_list args;
 
-  return r;
+  va_start (args, request);
+  arg = va_arg (args, void *);
+  va_end (args);
 
+# if WINDOWS_SOCKETS
+  return execute_all_ioctl_hooks (primary_ioctl, fd, request, arg);
 # else
-  errno = ENOSYS;
-  return -1;
+  return primary_ioctl (fd, request, arg);
 # endif
 }
 
diff --git a/lib/sockets.c b/lib/sockets.c
index 4e905e1ddd..42b8f9ea58 100644
--- a/lib/sockets.c
+++ b/lib/sockets.c
@@ -27,13 +27,15 @@
 /* This includes winsock2.h on MinGW. */
 # include <sys/socket.h>
 
-# include "close-hook.h"
+# include "fd-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)
+close_fd_maybe_socket (const struct fd_hook *remaining_list,
+                       gl_close_fn primary,
+                       int fd)
 {
   SOCKET sock;
   WSANETWORKEVENTS ev;
@@ -64,10 +66,38 @@ close_fd_maybe_socket (int fd, const struct close_hook *remaining_list)
     }
   else
     /* Some other type of file descriptor.  */
-    return execute_close_hooks (fd, remaining_list);
+    return execute_close_hooks (remaining_list, primary, fd);
 }
 
-static struct close_hook close_sockets_hook;
+static int
+ioctl_fd_maybe_socket (const struct fd_hook *remaining_list,
+                       gl_ioctl_fn primary,
+                       int fd, int request, void *arg)
+{
+  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.  */
+      if (ioctlsocket (sock, request, arg) < 0)
+        {
+          set_winsock_errno ();
+          return -1;
+        }
+      else
+        return 0;
+    }
+  else
+    /* Some other type of file descriptor.  */
+    return execute_ioctl_hooks (remaining_list, primary, fd, request, arg);
+}
+
+static struct fd_hook fd_sockets_hook;
 
 static int initialized_sockets_version /* = 0 */;
 
@@ -90,7 +120,8 @@ gl_sockets_startup (int version _GL_UNUSED)
         return 2;
 
       if (initialized_sockets_version == 0)
-        register_close_hook (close_fd_maybe_socket, &close_sockets_hook);
+        register_fd_hook (close_fd_maybe_socket, ioctl_fd_maybe_socket,
+                          &fd_sockets_hook);
 
       initialized_sockets_version = version;
     }
@@ -107,7 +138,7 @@ gl_sockets_cleanup (void)
 
   initialized_sockets_version = 0;
 
-  unregister_close_hook (&close_sockets_hook);
+  unregister_fd_hook (&fd_sockets_hook);
 
   err = WSACleanup ();
   if (err != 0)
diff --git a/modules/close b/modules/close
index e294292b02..88e1608726 100644
--- a/modules/close
+++ b/modules/close
@@ -7,7 +7,7 @@ m4/close.m4
 
 Depends-on:
 unistd
-close-hook
+fd-hook
 fclose
 
 configure.ac:
diff --git a/modules/close-hook b/modules/close-hook
deleted file mode 100644
index ae32ad0530..0000000000
--- a/modules/close-hook
+++ /dev/null
@@ -1,23 +0,0 @@
-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
diff --git a/modules/fd-hook b/modules/fd-hook
new file mode 100644
index 0000000000..7127083763
--- /dev/null
+++ b/modules/fd-hook
@@ -0,0 +1,23 @@
+Description:
+Hook for making file descriptor functions (close(), ioctl()) extensible.
+
+Files:
+lib/fd-hook.h
+lib/fd-hook.c
+
+Depends-on:
+unistd
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += fd-hook.c
+
+Include:
+"fd-hook.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
diff --git a/modules/ioctl b/modules/ioctl
index 5ba70ed98c..6a54f0318b 100644
--- a/modules/ioctl
+++ b/modules/ioctl
@@ -10,6 +10,7 @@ Depends-on:
 sys_ioctl
 sys_socket
 errno
+fd-hook
 
 configure.ac:
 gl_FUNC_IOCTL
diff --git a/modules/sockets b/modules/sockets
index b79a02fb7c..fe9292631c 100644
--- a/modules/sockets
+++ b/modules/sockets
@@ -10,7 +10,7 @@ m4/sockets.m4
 Depends-on:
 socketlib
 sys_socket
-close-hook
+fd-hook
 
 configure.ac:
 gl_SOCKETS
diff --git a/tests/test-nonblocking.c b/tests/test-nonblocking.c
index bfeef7bf71..f3f1f1355b 100644
--- a/tests/test-nonblocking.c
+++ b/tests/test-nonblocking.c
@@ -79,7 +79,7 @@ main (void)
   ASSERT (close (fd_pipe[1]) == 0);
 #endif /* GNULIB_TEST_PIPE2 */
 
-#if GNULIB_SOCKET
+#if GNULIB_TEST_SOCKET
   {
     /* Test sockets.  */
     bool sock_works = true;
@@ -104,7 +104,7 @@ main (void)
     ASSERT (close (fd_sock) == 0);
 # endif /* SOCK_NONBLOCK */
   }
-#endif /* GNULIB_SOCKET */
+#endif /* GNULIB_TEST_SOCKET */
 
   /* Test error handling.  */
   {
-- 
2.39.5