Merge commit 'b4bf0cf0458759c67920a031021a9d96cd683cfe'
[unleashed.git] / kernel / syscall / sigaction.c
blob3fabff298693fc0971cc3f60f6009f77c0e7c42a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/systm.h>
34 #include <sys/user.h>
35 #include <sys/errno.h>
36 #include <sys/proc.h>
37 #include <sys/fault.h>
38 #include <sys/signal.h>
39 #include <sys/siginfo.h>
40 #include <sys/debug.h>
42 int
43 sigaction(int sig, struct sigaction *actp, struct sigaction *oactp)
45 struct sigaction act;
46 struct sigaction oact;
47 k_sigset_t set;
48 proc_t *p;
49 user_t *ua;
50 int sigcld_look = 0;
52 if (sig <= 0 || sig >= NSIG ||
53 (actp != NULL && sigismember(&cantmask, sig)))
54 return (set_errno(EINVAL));
57 * act and oact might be the same address, so copyin act first.
59 if (actp) {
60 if (copyin(actp, &act, sizeof (act)))
61 return (set_errno(EFAULT));
64 p = curproc;
65 ua = PTOU(p);
66 mutex_enter(&p->p_lock);
68 if (oactp) {
69 int flags;
70 void (*disp)();
72 disp = ua->u_signal[sig - 1];
74 flags = 0;
75 if (disp != SIG_DFL && disp != SIG_IGN) {
76 set = ua->u_sigmask[sig-1];
77 if (sigismember(&p->p_siginfo, sig))
78 flags |= SA_SIGINFO;
79 if (sigismember(&ua->u_sigrestart, sig))
80 flags |= SA_RESTART;
81 if (sigismember(&ua->u_sigonstack, sig))
82 flags |= SA_ONSTACK;
83 if (sigismember(&ua->u_sigresethand, sig))
84 flags |= SA_RESETHAND;
85 if (sigismember(&ua->u_signodefer, sig))
86 flags |= SA_NODEFER;
87 } else
88 sigemptyset(&set);
90 if (sig == SIGCLD) {
91 if (p->p_flag & SNOWAIT)
92 flags |= SA_NOCLDWAIT;
93 if (!(p->p_flag & SJCTL))
94 flags |= SA_NOCLDSTOP;
97 oact.sa_handler = disp;
98 oact.sa_flags = flags;
99 sigktou(&set, &oact.sa_mask);
102 if (actp) {
103 if (sig == SIGCLD)
104 sigcld_look = 1;
105 sigutok(&act.sa_mask, &set);
106 setsigact(sig, act.sa_handler, &set, act.sa_flags);
109 mutex_exit(&p->p_lock);
111 if (sigcld_look)
112 sigcld_repost();
114 if (oactp &&
115 copyout(&oact, oactp, sizeof (oact)))
116 return (set_errno(EFAULT));
118 return (0);
121 #ifdef _SYSCALL32_IMPL
124 sigaction32(int sig, struct sigaction32 *actp, struct sigaction32 *oactp)
126 struct sigaction32 act32;
127 struct sigaction32 oact32;
128 k_sigset_t set;
129 proc_t *p;
130 user_t *ua;
131 int sigcld_look = 0;
133 if (sig <= 0 || sig >= NSIG ||
134 (actp != NULL && sigismember(&cantmask, sig)))
135 return (set_errno(EINVAL));
138 * act and oact might be the same address, so copyin act first.
140 if (actp) {
141 #if defined(__sparc)
142 void (*handler)();
143 #endif
144 if (copyin(actp, &act32, sizeof (act32)))
145 return (set_errno(EFAULT));
146 #if defined(__sparc)
148 * Check alignment of handler
150 handler = (void (*)())(uintptr_t)act32.sa_handler;
151 if (handler != SIG_IGN && handler != SIG_DFL &&
152 ((uintptr_t)handler & 0x3) != 0)
153 return (set_errno(EINVAL));
154 #endif
157 p = curproc;
158 ua = PTOU(p);
159 mutex_enter(&p->p_lock);
161 if (oactp) {
162 int flags;
163 void (*disp)();
165 disp = ua->u_signal[sig - 1];
167 flags = 0;
168 if (disp != SIG_DFL && disp != SIG_IGN) {
169 set = ua->u_sigmask[sig-1];
170 if (sigismember(&p->p_siginfo, sig))
171 flags |= SA_SIGINFO;
172 if (sigismember(&ua->u_sigrestart, sig))
173 flags |= SA_RESTART;
174 if (sigismember(&ua->u_sigonstack, sig))
175 flags |= SA_ONSTACK;
176 if (sigismember(&ua->u_sigresethand, sig))
177 flags |= SA_RESETHAND;
178 if (sigismember(&ua->u_signodefer, sig))
179 flags |= SA_NODEFER;
180 } else
181 sigemptyset(&set);
183 if (sig == SIGCLD) {
184 if (p->p_flag & SNOWAIT)
185 flags |= SA_NOCLDWAIT;
186 if (!(p->p_flag & SJCTL))
187 flags |= SA_NOCLDSTOP;
190 oact32.sa_handler = (caddr32_t)(uintptr_t)disp;
191 oact32.sa_flags = flags;
192 sigktou(&set, &oact32.sa_mask);
195 if (actp) {
196 if (sig == SIGCLD)
197 sigcld_look = 1;
198 sigutok(&act32.sa_mask, &set);
199 setsigact(sig, (void (*)())(uintptr_t)act32.sa_handler, &set,
200 act32.sa_flags);
203 mutex_exit(&p->p_lock);
205 if (sigcld_look)
206 sigcld_repost();
208 if (oactp &&
209 copyout(&oact32, oactp, sizeof (oact32)))
210 return (set_errno(EFAULT));
212 return (0);
214 #endif /* _SYSCALL32_IMPL */