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