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