xref: /netbsd-src/external/gpl3/gdb/dist/gnulib/import/fd-hook.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
18dffb485Schristos /* Hook for making file descriptor functions close(), ioctl() extensible.
2*4b169a6bSchristos    Copyright (C) 2009-2022 Free Software Foundation, Inc.
38dffb485Schristos    Written by Bruno Haible <bruno@clisp.org>, 2009.
48dffb485Schristos 
5*4b169a6bSchristos    This file is free software: you can redistribute it and/or modify
6*4b169a6bSchristos    it under the terms of the GNU Lesser General Public License as
7*4b169a6bSchristos    published by the Free Software Foundation; either version 2.1 of the
8*4b169a6bSchristos    License, or (at your option) any later version.
98dffb485Schristos 
10*4b169a6bSchristos    This file is distributed in the hope that it will be useful,
118dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
12*4b169a6bSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*4b169a6bSchristos    GNU Lesser General Public License for more details.
148dffb485Schristos 
15*4b169a6bSchristos    You should have received a copy of the GNU Lesser General Public License
168dffb485Schristos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
178dffb485Schristos 
188dffb485Schristos #include <config.h>
198dffb485Schristos 
208dffb485Schristos /* Specification.  */
218dffb485Schristos #include "fd-hook.h"
228dffb485Schristos 
238dffb485Schristos #include <stdlib.h>
248dffb485Schristos 
258dffb485Schristos /* Currently, this entire code is only needed for the handling of sockets
268dffb485Schristos    on native Windows platforms.  */
278dffb485Schristos #if WINDOWS_SOCKETS
288dffb485Schristos 
298dffb485Schristos /* The first and last link in the doubly linked list.
308dffb485Schristos    Initially the list is empty.  */
318dffb485Schristos static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
328dffb485Schristos 
338dffb485Schristos int
execute_close_hooks(const struct fd_hook * remaining_list,gl_close_fn primary,int fd)348dffb485Schristos execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
358dffb485Schristos                      int fd)
368dffb485Schristos {
378dffb485Schristos   if (remaining_list == &anchor)
388dffb485Schristos     /* End of list reached.  */
398dffb485Schristos     return primary (fd);
408dffb485Schristos   else
418dffb485Schristos     return remaining_list->private_close_fn (remaining_list->private_next,
428dffb485Schristos                                              primary, fd);
438dffb485Schristos }
448dffb485Schristos 
458dffb485Schristos int
execute_all_close_hooks(gl_close_fn primary,int fd)468dffb485Schristos execute_all_close_hooks (gl_close_fn primary, int fd)
478dffb485Schristos {
488dffb485Schristos   return execute_close_hooks (anchor.private_next, primary, fd);
498dffb485Schristos }
508dffb485Schristos 
518dffb485Schristos int
execute_ioctl_hooks(const struct fd_hook * remaining_list,gl_ioctl_fn primary,int fd,int request,void * arg)528dffb485Schristos execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
538dffb485Schristos                      int fd, int request, void *arg)
548dffb485Schristos {
558dffb485Schristos   if (remaining_list == &anchor)
568dffb485Schristos     /* End of list reached.  */
578dffb485Schristos     return primary (fd, request, arg);
588dffb485Schristos   else
598dffb485Schristos     return remaining_list->private_ioctl_fn (remaining_list->private_next,
608dffb485Schristos                                              primary, fd, request, arg);
618dffb485Schristos }
628dffb485Schristos 
638dffb485Schristos int
execute_all_ioctl_hooks(gl_ioctl_fn primary,int fd,int request,void * arg)648dffb485Schristos execute_all_ioctl_hooks (gl_ioctl_fn primary,
658dffb485Schristos                          int fd, int request, void *arg)
668dffb485Schristos {
678dffb485Schristos   return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
688dffb485Schristos }
698dffb485Schristos 
708dffb485Schristos void
register_fd_hook(close_hook_fn close_hook,ioctl_hook_fn ioctl_hook,struct fd_hook * link)718dffb485Schristos register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
728dffb485Schristos {
738dffb485Schristos   if (close_hook == NULL)
748dffb485Schristos     close_hook = execute_close_hooks;
758dffb485Schristos   if (ioctl_hook == NULL)
768dffb485Schristos     ioctl_hook = execute_ioctl_hooks;
778dffb485Schristos 
788dffb485Schristos   if (link->private_next == NULL && link->private_prev == NULL)
798dffb485Schristos     {
808dffb485Schristos       /* Add the link to the doubly linked list.  */
818dffb485Schristos       link->private_next = anchor.private_next;
828dffb485Schristos       link->private_prev = &anchor;
838dffb485Schristos       link->private_close_fn = close_hook;
848dffb485Schristos       link->private_ioctl_fn = ioctl_hook;
858dffb485Schristos       anchor.private_next->private_prev = link;
868dffb485Schristos       anchor.private_next = link;
878dffb485Schristos     }
888dffb485Schristos   else
898dffb485Schristos     {
908dffb485Schristos       /* The link is already in use.  */
918dffb485Schristos       if (link->private_close_fn != close_hook
928dffb485Schristos           || link->private_ioctl_fn != ioctl_hook)
938dffb485Schristos         abort ();
948dffb485Schristos     }
958dffb485Schristos }
968dffb485Schristos 
978dffb485Schristos void
unregister_fd_hook(struct fd_hook * link)988dffb485Schristos unregister_fd_hook (struct fd_hook *link)
998dffb485Schristos {
1008dffb485Schristos   struct fd_hook *next = link->private_next;
1018dffb485Schristos   struct fd_hook *prev = link->private_prev;
1028dffb485Schristos 
1038dffb485Schristos   if (next != NULL && prev != NULL)
1048dffb485Schristos     {
1058dffb485Schristos       /* The link is in use.  Remove it from the doubly linked list.  */
1068dffb485Schristos       prev->private_next = next;
1078dffb485Schristos       next->private_prev = prev;
1088dffb485Schristos       /* Clear the link, to mark it unused.  */
1098dffb485Schristos       link->private_next = NULL;
1108dffb485Schristos       link->private_prev = NULL;
1118dffb485Schristos       link->private_close_fn = NULL;
1128dffb485Schristos       link->private_ioctl_fn = NULL;
1138dffb485Schristos     }
1148dffb485Schristos }
1158dffb485Schristos 
1168dffb485Schristos #endif
117