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 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 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 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 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 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 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