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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
35 * 4.3BSD signal compatibility functions
37 * the implementation interprets signal masks equal to -1 as "all of the
38 * signals in the signal set", thereby allowing signals with numbers
39 * above 32 to be blocked when referenced in code such as:
41 * for (i = 0; i < NSIG; i++)
45 #include <sys/types.h>
50 #undef BUS_OBJERR /* namespace conflict */
51 #include <sys/siginfo.h>
54 #pragma weak sigvechandler = _sigvechandler
55 #pragma weak sigsetmask = _sigsetmask
56 #pragma weak sigblock = _sigblock
57 #pragma weak sigpause = usigpause
58 #pragma weak sigvec = _sigvec
59 #pragma weak sigstack = _sigstack
60 #pragma weak signal = usignal
61 #pragma weak siginterrupt = _siginterrupt
63 #define set2mask(setp) ((setp)->__sigbits[0])
64 #define mask2set(mask, setp) \
65 ((mask) == -1 ? sigfillset(setp) : \
66 (sigemptyset(setp), (((setp)->__sigbits[0]) = (int)(mask))))
68 void (*_siguhandler
[NSIG
])() = { 0 };
70 /* forward declarations */
71 int ucbsigsetmask(int);
73 int ucbsigvec(int, struct sigvec
*, struct sigvec
*);
75 int ucbsiginterrupt(int, int);
78 * sigvechandler is the real signal handler installed for all
79 * signals handled in the 4.3BSD compatibility interface - it translates
80 * SVR4 signal hander arguments into 4.3BSD signal handler arguments
81 * and then calls the real handler
84 static void ucbsigvechandler();
86 _sigvechandler(int sig
, siginfo_t
*sip
, ucontext_t
*ucp
)
89 ucbsigvechandler(sig
, sip
, ucp
);
93 ucbsigvechandler(int sig
, siginfo_t
*sip
, ucontext_t
*ucp
)
101 sc
.sc_onstack
= ((ucp
->uc_stack
.ss_flags
& SS_ONSTACK
) != 0);
102 sc
.sc_mask
= set2mask(&ucp
->uc_sigmask
);
105 sc
.sc_sp
= (long)ucp
->uc_mcontext
.gregs
[REG_RSP
];
106 sc
.sc_pc
= (long)ucp
->uc_mcontext
.gregs
[REG_RIP
];
107 sc
.sc_ps
= (long)ucp
->uc_mcontext
.gregs
[REG_RFL
];
108 sc
.sc_r0
= (long)ucp
->uc_mcontext
.gregs
[REG_RAX
];
109 sc
.sc_r1
= (long)ucp
->uc_mcontext
.gregs
[REG_RDX
];
111 sc
.sc_sp
= (int)ucp
->uc_mcontext
.gregs
[UESP
];
112 sc
.sc_pc
= (int)ucp
->uc_mcontext
.gregs
[EIP
];
113 sc
.sc_ps
= (int)ucp
->uc_mcontext
.gregs
[EFL
];
114 sc
.sc_r0
= (int)ucp
->uc_mcontext
.gregs
[EAX
];
115 sc
.sc_r1
= (int)ucp
->uc_mcontext
.gregs
[EDX
];
119 * Translate signal codes from new to old.
120 * /usr/include/sys/siginfo.h contains new codes.
121 * /usr/ucbinclude/sys/signal.h contains old codes.
125 if (sip
!= NULL
&& SI_FROMKERNEL(sip
)) {
131 code
= ILL_ILLINSTR_FAULT
;
135 switch (sip
->si_code
) {
142 default: /* BUS_OBJERR */
143 code
= FC_MAKE_ERR(sip
->si_errno
);
149 switch (sip
->si_code
) {
157 code
= FC_MAKE_ERR(sip
->si_errno
);
168 (*_siguhandler
[sig
])(sig
, code
, &sc
, addr
);
171 ucp
->uc_stack
.ss_flags
|= SS_ONSTACK
;
173 ucp
->uc_stack
.ss_flags
&= ~SS_ONSTACK
;
174 mask2set(sc
.sc_mask
, &ucp
->uc_sigmask
);
177 ucp
->uc_mcontext
.gregs
[REG_RSP
] = (long)sc
.sc_sp
;
178 ucp
->uc_mcontext
.gregs
[REG_RIP
] = (long)sc
.sc_pc
;
179 ucp
->uc_mcontext
.gregs
[REG_RFL
] = (long)sc
.sc_ps
;
180 ucp
->uc_mcontext
.gregs
[REG_RAX
] = (long)sc
.sc_r0
;
181 ucp
->uc_mcontext
.gregs
[REG_RDX
] = (long)sc
.sc_r1
;
183 ucp
->uc_mcontext
.gregs
[UESP
] = (int)sc
.sc_sp
;
184 ucp
->uc_mcontext
.gregs
[EIP
] = (int)sc
.sc_pc
;
185 ucp
->uc_mcontext
.gregs
[EFL
] = (int)sc
.sc_ps
;
186 ucp
->uc_mcontext
.gregs
[EAX
] = (int)sc
.sc_r0
;
187 ucp
->uc_mcontext
.gregs
[EDX
] = (int)sc
.sc_r1
;
194 _sigsetmask(int mask
)
196 return (ucbsigsetmask(mask
));
200 ucbsigsetmask(int mask
)
205 (void) sigprocmask(0, (sigset_t
*)0, &nset
);
206 mask2set(mask
, &nset
);
207 (void) sigprocmask(SIG_SETMASK
, &nset
, &oset
);
208 return (set2mask(&oset
));
214 return (ucbsigblock(mask
));
218 ucbsigblock(int mask
)
223 (void) sigprocmask(0, (sigset_t
*)0, &nset
);
224 mask2set(mask
, &nset
);
225 (void) sigprocmask(SIG_BLOCK
, &nset
, &oset
);
226 return (set2mask(&oset
));
232 return (ucbsigpause(mask
));
236 ucbsigpause(int mask
)
241 (void) sigprocmask(0, (sigset_t
*)0, &set
);
243 mask2set(mask
, &set
);
244 ret
= sigsuspend(&set
);
245 (void) sigprocmask(SIG_SETMASK
, &oset
, (sigset_t
*)0);
250 _sigvec(int sig
, struct sigvec
*nvec
, struct sigvec
*ovec
)
252 return (ucbsigvec(sig
, nvec
, ovec
));
256 ucbsigvec(int sig
, struct sigvec
*nvec
, struct sigvec
*ovec
)
258 struct sigaction nact
;
259 struct sigaction oact
;
260 struct sigaction
*nactp
;
261 void (*ohandler
)(), (*nhandler
)();
263 if (sig
<= 0 || sig
>= NSIG
) {
268 if ((intptr_t)ovec
== -1 || (intptr_t)nvec
== -1) {
273 ohandler
= _siguhandler
[sig
];
276 _sigaction(sig
, (struct sigaction
*)0, &nact
);
277 nhandler
= nvec
->sv_handler
;
279 * To be compatible with the behavior of SunOS 4.x:
280 * If the new signal handler is SIG_IGN or SIG_DFL,
281 * do not change the signal's entry in the handler array.
282 * This allows a child of vfork(2) to set signal handlers
283 * to SIG_IGN or SIG_DFL without affecting the parent.
285 if (nhandler
!= SIG_DFL
&& nhandler
!= SIG_IGN
) {
286 _siguhandler
[sig
] = nhandler
;
287 nact
.sa_handler
= (void (*)())ucbsigvechandler
;
289 nact
.sa_handler
= nhandler
;
291 mask2set(nvec
->sv_mask
, &nact
.sa_mask
);
292 if (sig
== SIGKILL
|| sig
== SIGSTOP
)
293 nact
.sa_handler
= SIG_DFL
;
294 nact
.sa_flags
= SA_SIGINFO
;
295 if (!(nvec
->sv_flags
& SV_INTERRUPT
))
296 nact
.sa_flags
|= SA_RESTART
;
297 if (nvec
->sv_flags
& SV_RESETHAND
)
298 nact
.sa_flags
|= SA_RESETHAND
;
299 if (nvec
->sv_flags
& SV_ONSTACK
)
300 nact
.sa_flags
|= SA_ONSTACK
;
303 nactp
= (struct sigaction
*)0;
305 if (_sigaction(sig
, nactp
, &oact
) < 0) {
306 _siguhandler
[sig
] = ohandler
;
311 if (oact
.sa_handler
== SIG_DFL
|| oact
.sa_handler
== SIG_IGN
)
312 ovec
->sv_handler
= oact
.sa_handler
;
314 ovec
->sv_handler
= ohandler
;
315 ovec
->sv_mask
= set2mask(&oact
.sa_mask
);
317 if (oact
.sa_flags
& SA_ONSTACK
)
318 ovec
->sv_flags
|= SV_ONSTACK
;
319 if (oact
.sa_flags
& SA_RESETHAND
)
320 ovec
->sv_flags
|= SV_RESETHAND
;
321 if (!(oact
.sa_flags
& SA_RESTART
))
322 ovec
->sv_flags
|= SV_INTERRUPT
;
329 _sigstack(struct sigstack
*nss
, struct sigstack
*oss
)
331 struct sigaltstack nalt
;
332 struct sigaltstack oalt
;
333 struct sigaltstack
*naltp
;
337 * assumes stack growth is down (like sparc and x86)
339 nalt
.ss_sp
= nss
->ss_sp
- SIGSTKSZ
;
340 nalt
.ss_size
= SIGSTKSZ
;
344 naltp
= (struct sigaltstack
*)0;
346 if (sigaltstack(naltp
, &oalt
) < 0)
351 * assumes stack growth is down (like sparc and x86)
353 oss
->ss_sp
= oalt
.ss_sp
+ oalt
.ss_size
;
354 oss
->ss_onstack
= ((oalt
.ss_flags
& SS_ONSTACK
) != 0);
361 ucbsignal(int s
, void (*a
)()))()
365 static int mask
[NSIG
];
366 static int flags
[NSIG
];
369 nsv
.sv_mask
= mask
[s
];
370 nsv
.sv_flags
= flags
[s
];
371 if (ucbsigvec(s
, &nsv
, &osv
) < 0)
373 if (nsv
.sv_mask
!= osv
.sv_mask
|| nsv
.sv_flags
!= osv
.sv_flags
) {
374 mask
[s
] = nsv
.sv_mask
= osv
.sv_mask
;
375 flags
[s
] = nsv
.sv_flags
=
376 osv
.sv_flags
& ~(SV_RESETHAND
|SV_INTERRUPT
);
377 if (ucbsigvec(s
, &nsv
, (struct sigvec
*)0) < 0)
380 return (osv
.sv_handler
);
384 usignal(int s
, void (*a
)()))()
386 return (ucbsignal(s
, a
));
390 * Set signal state to prevent restart of system calls
391 * after an instance of the indicated signal.
394 _siginterrupt(int sig
, int flag
)
396 return (ucbsiginterrupt(sig
, flag
));
400 ucbsiginterrupt(int sig
, int flag
)
405 if ((ret
= ucbsigvec(sig
, 0, &sv
)) < 0)
408 sv
.sv_flags
|= SV_INTERRUPT
;
410 sv
.sv_flags
&= ~SV_INTERRUPT
;
411 return (ucbsigvec(sig
, &sv
, 0));