OSDN Git Service

sparc/sigaction.c: note possible bugs by comments. style fixes
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / sparc / sigaction.c
1 /* POSIX.1 sigaction call for Linux/SPARC.
2    Copyright (C) 1997-2000,2002,2003,2005 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Miguel de Icaza (miguel@nuclecu.unam.mx), 1997.
5
6    The GNU C Library 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        Ported to uClibc from glibc: 090520:
22                Jan Buchholz, KIP, Uni Heidelberg <jan.buchholz@kip.uni-heidelberg.de>
23                Austin Foxley, Ceton Corporation <austinf@cetoncorp.com>
24 */
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <string.h>
29 #include <sys/syscall.h>
30 #include <bits/kernel_sigaction.h>
31
32
33 _syscall5(int, rt_sigaction, int, a, int, b, int, c, int, d, int, e);
34 static void __rt_sigreturn_stub(void);
35 static void __sigreturn_stub(void);
36
37 int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
38 {
39         int ret;
40         struct old_kernel_sigaction kact, koact;
41         unsigned long stub = 0;
42         int saved_errno = errno;
43
44         if (act) {
45                 kact.k_sa_handler = act->sa_handler;
46                 // BUG?! kact.sa_mask is a long, but sigset_t is a vector
47                 // of longs and it may be bigger (in glibc, it _is_ bigger).
48                 // Should we do this instead?
49                 // kact.sa_mask = act->sa_mask.__val[0];
50                 memcpy(&kact.sa_mask, &act->sa_mask, sizeof(sigset_t));
51                 kact.sa_flags = act->sa_flags;
52                 if (kact.sa_flags & SA_SIGINFO)
53                         stub = (unsigned long) &__rt_sigreturn_stub;
54                 else
55                         stub = (unsigned long) &__sigreturn_stub;
56                 stub -= 8;
57                 kact.sa_restorer = NULL;
58         }
59         /* NB: kernel (as of 2.6.25) will return EINVAL
60          * if _NSIG / 8 does not match kernel's sizeof(sigset_t) */
61         ret = rt_sigaction(sig,
62                 (int)(act ? &kact : NULL),
63                 (int)(oact ? &koact : NULL),
64                 stub,
65                 _NSIG / 8);
66
67         // BUG?! if ret == -1, we return -1 but do not set errno?!
68         if (ret >= 0 || errno != ENOSYS) {
69                 if (oact && ret >= 0) {
70                         oact->sa_handler = koact.k_sa_handler;
71                         // maybe oact->sa_mask.__val[0] = koact.sa_mask; ?
72                         memcpy(&oact->sa_mask, &koact.sa_mask, sizeof(sigset_t));
73                         oact->sa_flags = koact.sa_flags;
74                         oact->sa_restorer = koact.sa_restorer;
75                 }
76                 return ret;
77         }
78         __set_errno(saved_errno);
79         return -1;
80 }
81
82 #ifndef LIBC_SIGACTION
83 weak_alias(__libc_sigaction,sigaction)
84 libc_hidden_weak(sigaction)
85 #endif
86
87 static void
88 __rt_sigreturn_stub(void)
89 {
90         __asm__(
91                 "mov %0, %%g1\n\t"
92                 "ta  0x10\n\t"
93                 : /* no outputs */
94                 : "i" (__NR_rt_sigreturn)
95         );
96 }
97 static void
98 __sigreturn_stub(void)
99 {
100         __asm__(
101                 "mov %0, %%g1\n\t"
102                 "ta  0x10\n\t"
103                 : /* no outputs */
104                 : "i" (__NR_sigreturn)
105         );
106 }