]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigwait.c
Inital import
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / signal / sigwait.c
1 /* vi: set sw=4 ts=4: */
2 /* sigwait
3  *
4  * Copyright (C) 2003 by Erik Andersen <andersen@uclibc.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * The GNU C Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with the GNU C Library; if not, write to the Free
18  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19  * 02111-1307 USA.  */
20
21 #include <errno.h>
22 #include <signal.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #if defined __UCLIBC_HAS_REALTIME__
27
28 int sigwait(const sigset_t *set, int *sig)
29 {
30         int ret = sigwaitinfo(set, NULL);
31         if (ret != -1) {
32                 *sig = ret;
33                 return 0;
34         }
35         return 1;
36 }
37
38 #else /* __UCLIBC_HAS_REALTIME__ */
39 /* variant without REALTIME extensions */
40
41 static smallint was_sig; /* obviously not thread-safe */
42
43 static void ignore_signal(int sig)
44 {
45         was_sig = sig;
46 }
47
48 int sigwait (const sigset_t *set, int *sig)
49 {
50   sigset_t tmp_mask;
51   struct sigaction saved[NSIG];
52   struct sigaction action;
53   int save_errno;
54   int this;
55
56   /* Prepare set.  */
57   __sigfillset (&tmp_mask);
58
59   /* Unblock all signals in the SET and register our nice handler.  */
60   action.sa_handler = ignore_signal;
61   action.sa_flags = 0;
62   __sigfillset (&action.sa_mask);       /* Block all signals for handler.  */
63
64   /* Make sure we recognize error conditions by setting WAS_SIG to a
65      value which does not describe a legal signal number.  */
66   was_sig = -1;
67
68   for (this = 1; this < NSIG; ++this)
69     if (__sigismember (set, this))
70       {
71         /* Unblock this signal.  */
72         __sigdelset (&tmp_mask, this);
73
74         /* Register temporary action handler.  */
75         /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */
76         /* (so, will it work correctly if set has, say, SIGSTOP?) */
77         if (sigaction (this, &action, &saved[this]) != 0)
78           goto restore_handler;
79       }
80
81   /* Now we can wait for signals.  */
82   sigsuspend (&tmp_mask);
83
84  restore_handler:
85   save_errno = errno;
86
87   while (--this >= 1)
88     if (__sigismember (set, this))
89       /* We ignore errors here since we must restore all handlers.  */
90       sigaction (this, &saved[this], NULL);
91
92   __set_errno (save_errno);
93
94   /* Store the result and return.  */
95   *sig = was_sig;
96   return was_sig == -1 ? -1 : 0;
97 }
98 #endif /* __UCLIBC_HAS_REALTIME__ */