(gaih_inet): Recognize all the IPv4 numeric address formats inet_addr knows.
[kopensolaris-gnu/glibc.git] / sysdeps / posix / sigvec.c
1 /* Copyright (C) 1991,92,94,95,96,97,98,2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <signal.h>
20 #include <errno.h>
21 #include <stddef.h>
22
23 /* Include macros to convert between `sigset_t' and old-style mask. */
24 #include <sigset-cvt-mask.h>
25
26 #ifndef SA_RESETHAND
27 /* When sigaction lacks the extension bit for it,
28    we use a wrapper handler to support SV_RESETHAND.  */
29 struct sigvec_wrapper_data
30 {
31   __sighandler_t sw_handler;
32   unsigned int sw_mask;
33 };
34
35 static void sigvec_wrapper_handler __P ((int sig));
36
37 static struct sigvec_wrapper_data sigvec_wrapper_data[NSIG];
38 #endif
39
40
41 /* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member
42    of VEC.  The signals in `sv_mask' will be blocked while the handler runs.
43    If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be
44    reset to SIG_DFL before `sv_handler' is entered.  If OVEC is non-NULL,
45    it is filled in with the old information for SIG.  */
46 int
47 __sigvec (sig, vec, ovec)
48      int sig;
49      const struct sigvec *vec;
50      struct sigvec *ovec;
51 {
52   struct sigaction old;
53
54 #ifndef SA_RESETHAND
55   if (vec == NULL || !(vec->sv_flags & SV_RESETHAND))
56 #endif
57     {
58       struct sigaction new, *n;
59
60       if (vec == NULL)
61         n = NULL;
62       else
63         {
64           __sighandler_t handler;
65           unsigned int mask;
66           unsigned int sv_flags;
67           unsigned int sa_flags;
68
69           handler = vec->sv_handler;
70           mask = vec->sv_mask;
71           sv_flags = vec->sv_flags;
72           sa_flags = 0;
73           if (sv_flags & SV_ONSTACK)
74             {
75 #ifdef SA_ONSTACK
76               sa_flags |= SA_ONSTACK;
77 #else
78               __set_errno (ENOSYS);
79               return -1;
80 #endif
81             }
82 #ifdef SA_RESTART
83           if (!(sv_flags & SV_INTERRUPT))
84             sa_flags |= SA_RESTART;
85 #endif
86 #ifdef SA_RESETHAND
87           if (sv_flags & SV_RESETHAND)
88             sa_flags |= SA_RESETHAND;
89 #endif
90           n = &new;
91           new.sa_handler = handler;
92           if (sigset_set_old_mask (&new.sa_mask, mask) < 0)
93             return -1;
94           new.sa_flags = sa_flags;
95         }
96
97       if (__sigaction (sig, n, &old) < 0)
98         return -1;
99     }
100 #ifndef SA_RESETHAND
101   else
102     {
103       __sighandler_t handler;
104       unsigned int mask;
105       struct sigvec_wrapper_data *data;
106       struct sigaction wrapper;
107
108       handler = vec->sv_handler;
109       mask = (unsigned int)vec->sv_mask;
110       data = &sigvec_wrapper_data[sig];
111       wrapper.sa_handler = sigvec_wrapper_handler;
112       /* FIXME: should we set wrapper.sa_mask, wrapper.sa_flags??  */
113       data->sw_handler = handler;
114       data->sw_mask = mask;
115
116       if (__sigaction (sig, &wrapper, &old) < 0)
117         return -1;
118     }
119 #endif
120
121   if (ovec != NULL)
122     {
123       __sighandler_t handler;
124       unsigned int sv_flags;
125       unsigned int sa_flags;
126       unsigned int mask;
127
128       handler = old.sa_handler;
129       sv_flags = 0;
130       sa_flags = old.sa_flags;
131 #ifndef SA_RESETHAND
132       if (handler == sigvec_wrapper_handler)
133         {
134           handler = sigvec_wrapper_data[sig].sw_handler;
135           /* should we use data->sw_mask?? */
136           sv_flags |= SV_RESETHAND;
137         }
138 #else
139      if (sa_flags & SA_RESETHAND)
140         sv_flags |= SV_RESETHAND;
141 #endif
142       mask = sigset_get_old_mask (&old.sa_mask);
143 #ifdef SA_ONSTACK
144      if (sa_flags & SA_ONSTACK)
145         sv_flags |= SV_ONSTACK;
146 #endif
147 #ifdef SA_RESTART
148      if (!(sa_flags & SA_RESTART))
149 #endif
150         sv_flags |= SV_INTERRUPT;
151       ovec->sv_handler = handler;
152       ovec->sv_mask = (int)mask;
153       ovec->sv_flags = (int)sv_flags;
154     }
155
156   return 0;
157 }
158
159 weak_alias (__sigvec, sigvec)
160
161 #ifndef SA_RESETHAND
162 static void
163 sigvec_wrapper_handler (sig)
164      int sig;
165 {
166   struct sigvec_wrapper_data *data;
167   struct sigaction act;
168   int save;
169   __sighandler_t handler;
170
171   data = &sigvec_wrapper_data[sig];
172   act.sa_handler = SIG_DFL;
173   act.sa_flags = 0;
174   sigset_set_old_mask (&act.sa_mask, data->sw_mask);
175   handler = data->sw_handler;
176   save = errno;
177   (void) __sigaction (sig, &act, (struct sigaction *) NULL);
178   __set_errno (save);
179
180   (*handler) (sig);
181 }
182 #endif