• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* POSIX compatible signal blocking.
2   Copyright (C) 2006-2007 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2006.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include <signal.h>
22
23#include <errno.h>
24#include <stdint.h>
25#include <stdlib.h>
26
27/* We assume that a platform without POSIX signal blocking functions also
28   does not have the POSIX sigaction() function, only the signal() function.
29   This is true for Woe32 platforms.  */
30
31/* A signal handler.  */
32typedef void (*handler_t) (int signal);
33
34int
35sigismember (const sigset_t *set, int sig)
36{
37  if (sig >= 0 && sig < NSIG)
38    return (*set >> sig) & 1;
39  else
40    return 0;
41}
42
43int
44sigemptyset (sigset_t *set)
45{
46  *set = 0;
47  return 0;
48}
49
50int
51sigaddset (sigset_t *set, int sig)
52{
53  if (sig >= 0 && sig < NSIG)
54    {
55      *set |= 1U << sig;
56      return 0;
57    }
58  else
59    {
60      errno = EINVAL;
61      return -1;
62    }
63}
64
65int
66sigdelset (sigset_t *set, int sig)
67{
68  if (sig >= 0 && sig < NSIG)
69    {
70      *set &= ~(1U << sig);
71      return 0;
72    }
73  else
74    {
75      errno = EINVAL;
76      return -1;
77    }
78}
79
80int
81sigfillset (sigset_t *set)
82{
83  *set = (2U << (NSIG - 1)) - 1;
84  return 0;
85}
86
87/* Set of currently blocked signals.  */
88static sigset_t blocked_set /* = 0 */;
89
90/* Set of currently blocked and pending signals.  */
91static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */;
92
93/* Signal handler that is installed for blocked signals.  */
94static void
95blocked_handler (int sig)
96{
97  if (sig >= 0 && sig < NSIG)
98    pending_array[sig] = 1;
99}
100
101int
102sigpending (sigset_t *set)
103{
104  sigset_t pending = 0;
105  int sig;
106
107  for (sig = 0; sig < NSIG; sig++)
108    if (pending_array[sig])
109      pending |= 1U << sig;
110  return pending;
111}
112
113/* The previous signal handlers.
114   Only the array elements corresponding to blocked signals are relevant.  */
115static handler_t old_handlers[NSIG];
116
117int
118sigprocmask (int operation, const sigset_t *set, sigset_t *old_set)
119{
120  if (old_set != NULL)
121    *old_set = blocked_set;
122
123  if (set != NULL)
124    {
125      sigset_t new_blocked_set;
126      sigset_t to_unblock;
127      sigset_t to_block;
128
129      switch (operation)
130	{
131	case SIG_BLOCK:
132	  new_blocked_set = blocked_set | *set;
133	  break;
134	case SIG_SETMASK:
135	  new_blocked_set = *set;
136	  break;
137	case SIG_UNBLOCK:
138	  new_blocked_set = blocked_set & ~*set;
139	  break;
140	default:
141	  errno = EINVAL;
142	  return -1;
143	}
144      to_unblock = blocked_set & ~new_blocked_set;
145      to_block = new_blocked_set & ~blocked_set;
146
147      if (to_block != 0)
148	{
149	  int sig;
150
151	  for (sig = 0; sig < NSIG; sig++)
152	    if ((to_block >> sig) & 1)
153	      {
154		pending_array[sig] = 0;
155		if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR)
156		  blocked_set |= 1U << sig;
157	      }
158	}
159
160      if (to_unblock != 0)
161	{
162	  sig_atomic_t received[NSIG];
163	  int sig;
164
165	  for (sig = 0; sig < NSIG; sig++)
166	    if ((to_unblock >> sig) & 1)
167	      {
168		if (signal (sig, old_handlers[sig]) != blocked_handler)
169		  /* The application changed a signal handler while the signal
170		     was blocked.  We don't support this.  */
171		  abort ();
172		received[sig] = pending_array[sig];
173		blocked_set &= ~(1U << sig);
174		pending_array[sig] = 0;
175	      }
176	    else
177	      received[sig] = 0;
178
179	  for (sig = 0; sig < NSIG; sig++)
180	    if (received[sig])
181	      {
182		#if HAVE_RAISE
183		raise (sig);
184		#else
185		kill (getpid (), sig);
186		#endif
187	      }
188	}
189    }
190  return 0;
191}
192