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