xref: /dflybsd-src/contrib/grep/lib/fd-hook.c (revision 91b9ed38d3db6a8a8ac5b66da1d43e6e331e259a)
1*09d4459fSDaniel Fojt /* Hook for making file descriptor functions close(), ioctl() extensible.
2*09d4459fSDaniel Fojt    Copyright (C) 2009-2020 Free Software Foundation, Inc.
3cf28ed85SJohn Marino    Written by Bruno Haible <bruno@clisp.org>, 2009.
4cf28ed85SJohn Marino 
5cf28ed85SJohn Marino    This program is free software: you can redistribute it and/or modify it
6cf28ed85SJohn Marino    under the terms of the GNU General Public License as published
7cf28ed85SJohn Marino    by the Free Software Foundation; either version 3 of the License, or
8cf28ed85SJohn Marino    (at your option) any later version.
9cf28ed85SJohn Marino 
10cf28ed85SJohn Marino    This program is distributed in the hope that it will be useful,
11cf28ed85SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
12cf28ed85SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13cf28ed85SJohn Marino    General Public License for more details.
14cf28ed85SJohn Marino 
15cf28ed85SJohn Marino    You should have received a copy of the GNU General Public License
16*09d4459fSDaniel Fojt    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17cf28ed85SJohn Marino 
18cf28ed85SJohn Marino #include <config.h>
19cf28ed85SJohn Marino 
20cf28ed85SJohn Marino /* Specification.  */
21cf28ed85SJohn Marino #include "fd-hook.h"
22cf28ed85SJohn Marino 
23cf28ed85SJohn Marino #include <stdlib.h>
24cf28ed85SJohn Marino 
25cf28ed85SJohn Marino /* Currently, this entire code is only needed for the handling of sockets
26cf28ed85SJohn Marino    on native Windows platforms.  */
27cf28ed85SJohn Marino #if WINDOWS_SOCKETS
28cf28ed85SJohn Marino 
29cf28ed85SJohn Marino /* The first and last link in the doubly linked list.
30cf28ed85SJohn Marino    Initially the list is empty.  */
31cf28ed85SJohn Marino static struct fd_hook anchor = { &anchor, &anchor, NULL, NULL };
32cf28ed85SJohn Marino 
33cf28ed85SJohn Marino int
execute_close_hooks(const struct fd_hook * remaining_list,gl_close_fn primary,int fd)34cf28ed85SJohn Marino execute_close_hooks (const struct fd_hook *remaining_list, gl_close_fn primary,
35cf28ed85SJohn Marino                      int fd)
36cf28ed85SJohn Marino {
37cf28ed85SJohn Marino   if (remaining_list == &anchor)
38cf28ed85SJohn Marino     /* End of list reached.  */
39cf28ed85SJohn Marino     return primary (fd);
40cf28ed85SJohn Marino   else
41cf28ed85SJohn Marino     return remaining_list->private_close_fn (remaining_list->private_next,
42cf28ed85SJohn Marino                                              primary, fd);
43cf28ed85SJohn Marino }
44cf28ed85SJohn Marino 
45cf28ed85SJohn Marino int
execute_all_close_hooks(gl_close_fn primary,int fd)46cf28ed85SJohn Marino execute_all_close_hooks (gl_close_fn primary, int fd)
47cf28ed85SJohn Marino {
48cf28ed85SJohn Marino   return execute_close_hooks (anchor.private_next, primary, fd);
49cf28ed85SJohn Marino }
50cf28ed85SJohn Marino 
51cf28ed85SJohn Marino int
execute_ioctl_hooks(const struct fd_hook * remaining_list,gl_ioctl_fn primary,int fd,int request,void * arg)52cf28ed85SJohn Marino execute_ioctl_hooks (const struct fd_hook *remaining_list, gl_ioctl_fn primary,
53cf28ed85SJohn Marino                      int fd, int request, void *arg)
54cf28ed85SJohn Marino {
55cf28ed85SJohn Marino   if (remaining_list == &anchor)
56cf28ed85SJohn Marino     /* End of list reached.  */
57cf28ed85SJohn Marino     return primary (fd, request, arg);
58cf28ed85SJohn Marino   else
59cf28ed85SJohn Marino     return remaining_list->private_ioctl_fn (remaining_list->private_next,
60cf28ed85SJohn Marino                                              primary, fd, request, arg);
61cf28ed85SJohn Marino }
62cf28ed85SJohn Marino 
63cf28ed85SJohn Marino int
execute_all_ioctl_hooks(gl_ioctl_fn primary,int fd,int request,void * arg)64cf28ed85SJohn Marino execute_all_ioctl_hooks (gl_ioctl_fn primary,
65cf28ed85SJohn Marino                          int fd, int request, void *arg)
66cf28ed85SJohn Marino {
67cf28ed85SJohn Marino   return execute_ioctl_hooks (anchor.private_next, primary, fd, request, arg);
68cf28ed85SJohn Marino }
69cf28ed85SJohn Marino 
70cf28ed85SJohn Marino void
register_fd_hook(close_hook_fn close_hook,ioctl_hook_fn ioctl_hook,struct fd_hook * link)71cf28ed85SJohn Marino register_fd_hook (close_hook_fn close_hook, ioctl_hook_fn ioctl_hook, struct fd_hook *link)
72cf28ed85SJohn Marino {
73cf28ed85SJohn Marino   if (close_hook == NULL)
74cf28ed85SJohn Marino     close_hook = execute_close_hooks;
75cf28ed85SJohn Marino   if (ioctl_hook == NULL)
76cf28ed85SJohn Marino     ioctl_hook = execute_ioctl_hooks;
77cf28ed85SJohn Marino 
78cf28ed85SJohn Marino   if (link->private_next == NULL && link->private_prev == NULL)
79cf28ed85SJohn Marino     {
80cf28ed85SJohn Marino       /* Add the link to the doubly linked list.  */
81cf28ed85SJohn Marino       link->private_next = anchor.private_next;
82cf28ed85SJohn Marino       link->private_prev = &anchor;
83cf28ed85SJohn Marino       link->private_close_fn = close_hook;
84cf28ed85SJohn Marino       link->private_ioctl_fn = ioctl_hook;
85cf28ed85SJohn Marino       anchor.private_next->private_prev = link;
86cf28ed85SJohn Marino       anchor.private_next = link;
87cf28ed85SJohn Marino     }
88cf28ed85SJohn Marino   else
89cf28ed85SJohn Marino     {
90cf28ed85SJohn Marino       /* The link is already in use.  */
91cf28ed85SJohn Marino       if (link->private_close_fn != close_hook
92cf28ed85SJohn Marino           || link->private_ioctl_fn != ioctl_hook)
93cf28ed85SJohn Marino         abort ();
94cf28ed85SJohn Marino     }
95cf28ed85SJohn Marino }
96cf28ed85SJohn Marino 
97cf28ed85SJohn Marino void
unregister_fd_hook(struct fd_hook * link)98cf28ed85SJohn Marino unregister_fd_hook (struct fd_hook *link)
99cf28ed85SJohn Marino {
100cf28ed85SJohn Marino   struct fd_hook *next = link->private_next;
101cf28ed85SJohn Marino   struct fd_hook *prev = link->private_prev;
102cf28ed85SJohn Marino 
103cf28ed85SJohn Marino   if (next != NULL && prev != NULL)
104cf28ed85SJohn Marino     {
105cf28ed85SJohn Marino       /* The link is in use.  Remove it from the doubly linked list.  */
106cf28ed85SJohn Marino       prev->private_next = next;
107cf28ed85SJohn Marino       next->private_prev = prev;
108cf28ed85SJohn Marino       /* Clear the link, to mark it unused.  */
109cf28ed85SJohn Marino       link->private_next = NULL;
110cf28ed85SJohn Marino       link->private_prev = NULL;
111cf28ed85SJohn Marino       link->private_close_fn = NULL;
112cf28ed85SJohn Marino       link->private_ioctl_fn = NULL;
113cf28ed85SJohn Marino     }
114cf28ed85SJohn Marino }
115cf28ed85SJohn Marino 
116cf28ed85SJohn Marino #endif
117