011d4d5f44
* struct sigacts gets a new sigact_sigdesc structure, which has the sigaction and the trampoline/version. Version 0 means "legacy kernel provided trampoline". Other versions are coordinated with machine- dependent code in libc. * sigaction1() grows two more arguments -- the trampoline pointer and the trampoline version. * A new __sigaction_sigtramp() system call is provided to register a trampoline along with a signal handler. * The handler is no longer passed to sensig() functions. Instead, sendsig() looks up the handler by peeking in the sigacts for the process getting the signal (since it has to look in there for the trampoline anyway). * Native sendsig() functions now select the appropriate trampoline and its arguments based on the trampoline version in the sigacts. Changes to libc to use the new facility will be checked in later. Kernel version not bumped; we will ride the 1.6C bump made recently.
444 lines
11 KiB
C
444 lines
11 KiB
C
/* $NetBSD: hpux_sig.c,v 1.23 2002/07/04 23:32:09 thorpej Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 1988 University of Utah.
|
|
* Copyright (c) 1990, 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* the Systems Programming Group of the University of Utah Computer
|
|
* Science Department.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* from: Utah $Hdr: hpux_sig.c 1.4 92/01/20$
|
|
*
|
|
* @(#)hpux_sig.c 8.2 (Berkeley) 9/23/93
|
|
*/
|
|
|
|
/*
|
|
* Signal related HPUX compatibility routines
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: hpux_sig.c,v 1.23 2002/07/04 23:32:09 thorpej Exp $");
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/syscallargs.h>
|
|
|
|
#include <compat/hpux/hpux.h>
|
|
#include <compat/hpux/hpux_sig.h>
|
|
#include <compat/hpux/hpux_syscallargs.h>
|
|
|
|
extern const unsigned char native_to_hpux_signo[];
|
|
extern const unsigned char hpux_to_native_signo[];
|
|
|
|
/*
|
|
* XXX: In addition to mapping the signal number we also have
|
|
* to see if the "old" style signal mechinism is needed.
|
|
* If so, we set the OUSIG flag. This is not really correct
|
|
* as under HP-UX "old" style handling can be set on a per
|
|
* signal basis and we are setting it for all signals in one
|
|
* swell foop. I suspect we can get away with this since I
|
|
* doubt any program of interest mixes the two semantics.
|
|
*/
|
|
int
|
|
hpux_sys_sigvec(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigvec_args *uap = v;
|
|
struct sigvec nsv, osv;
|
|
struct sigaction nsa, osa;
|
|
int sig, error;
|
|
|
|
/* XXX */
|
|
extern void compat_43_sigvec_to_sigaction
|
|
__P((const struct sigvec *, struct sigaction *));
|
|
extern void compat_43_sigaction_to_sigvec
|
|
__P((const struct sigaction *, struct sigvec *));
|
|
|
|
/*
|
|
* XXX We don't handle HPUXSV_RESET!
|
|
*/
|
|
|
|
sig = hpuxtobsdsig(SCARG(uap, signo));
|
|
if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
|
|
return (EINVAL);
|
|
|
|
if (SCARG(uap, nsv)) {
|
|
error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv));
|
|
if (error)
|
|
return (error);
|
|
|
|
compat_43_sigvec_to_sigaction(&nsv, &nsa);
|
|
}
|
|
|
|
error = sigaction1(p, sig,
|
|
SCARG(uap, nsv) ? &nsa : NULL,
|
|
SCARG(uap, osv) ? &osa : NULL,
|
|
NULL, 0);
|
|
|
|
if (error)
|
|
return (error);
|
|
|
|
if (SCARG(uap, osv)) {
|
|
compat_43_sigaction_to_sigvec(&osa, &osv);
|
|
error = copyout(&osv, SCARG(uap, osv), sizeof(osv));
|
|
if (error)
|
|
return (error);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigblock(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigblock_args *uap = v;
|
|
sigset_t nmask;
|
|
|
|
(void) splsched();
|
|
|
|
bsdtohpuxmask(&p->p_sigctx.ps_sigmask, (int *)retval);
|
|
hpuxtobsdmask(SCARG(uap, mask), &nmask);
|
|
|
|
sigplusset(&nmask, &p->p_sigctx.ps_sigmask);
|
|
sigminusset(&sigcantmask, &p->p_sigctx.ps_sigmask);
|
|
|
|
(void) spl0();
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigsetmask(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigsetmask_args *uap = v;
|
|
|
|
(void) splsched();
|
|
|
|
bsdtohpuxmask(&p->p_sigctx.ps_sigmask, (int *)retval);
|
|
hpuxtobsdmask(SCARG(uap, mask), &p->p_sigctx.ps_sigmask);
|
|
|
|
sigminusset(&sigcantmask, &p->p_sigctx.ps_sigmask);
|
|
|
|
(void) spl0();
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigpause(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigpause_args *uap = v;
|
|
sigset_t mask;
|
|
|
|
hpuxtobsdmask(SCARG(uap, mask), &mask);
|
|
return (sigsuspend1(p, &mask));
|
|
}
|
|
|
|
/* not totally correct, but close enuf' */
|
|
int
|
|
hpux_sys_kill(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_kill_args *uap = v;
|
|
|
|
if (SCARG(uap, signo)) {
|
|
SCARG(uap, signo) = hpuxtobsdsig(SCARG(uap, signo));
|
|
if (SCARG(uap, signo) == 0)
|
|
SCARG(uap, signo) = NSIG;
|
|
}
|
|
return (sys_kill(p, uap, retval));
|
|
}
|
|
|
|
/*
|
|
* The following (sigprocmask, sigpending, sigsuspend, sigaction are
|
|
* POSIX calls. Under BSD, the library routine dereferences the sigset_t
|
|
* pointers before traping. Not so under HP-UX.
|
|
*/
|
|
|
|
/*
|
|
* Manipulate signal mask.
|
|
* Note that we receive new mask, not pointer,
|
|
* and return old mask as return value;
|
|
* the library stub does the rest.
|
|
*
|
|
* XXX We don't handle all HP-UX signals!
|
|
*/
|
|
int
|
|
hpux_sys_sigprocmask(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigprocmask_args *uap = v;
|
|
int error = 0;
|
|
hpux_sigset_t sigset;
|
|
sigset_t mask;
|
|
|
|
/*
|
|
* Copy out old mask first to ensure no errors.
|
|
* (proc sigmask should not be changed if call fails for any reason)
|
|
*/
|
|
if (SCARG(uap, oset)) {
|
|
memset((caddr_t)&sigset, 0, sizeof(sigset));
|
|
bsdtohpuxmask(&p->p_sigctx.ps_sigmask, &sigset.sigset[0]);
|
|
error = copyout(&sigset, SCARG(uap, oset), sizeof(sigset));
|
|
if (error)
|
|
return (error);
|
|
}
|
|
if (SCARG(uap, set)) {
|
|
error = copyin(SCARG(uap, set), &sigset, sizeof(sigset));
|
|
if (error)
|
|
return (error);
|
|
hpuxtobsdmask(sigset.sigset[0], &mask);
|
|
(void) splsched();
|
|
switch (SCARG(uap, how)) {
|
|
case HPUXSIG_BLOCK:
|
|
sigplusset(&mask, &p->p_sigctx.ps_sigmask);
|
|
sigminusset(&sigcantmask, &p->p_sigctx.ps_sigmask);
|
|
break;
|
|
case HPUXSIG_UNBLOCK:
|
|
sigminusset(&mask, &p->p_sigctx.ps_sigmask);
|
|
break;
|
|
case HPUXSIG_SETMASK:
|
|
p->p_sigctx.ps_sigmask = mask;
|
|
sigminusset(&sigcantmask, &p->p_sigctx.ps_sigmask);
|
|
break;
|
|
default:
|
|
error = EINVAL;
|
|
break;
|
|
}
|
|
(void) spl0();
|
|
}
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigpending(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigpending_args *uap = v;
|
|
hpux_sigset_t sigset;
|
|
|
|
bsdtohpuxmask(&p->p_sigctx.ps_siglist, &sigset.sigset[0]);
|
|
return (copyout(&sigset, SCARG(uap, set), sizeof(sigset)));
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigsuspend(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigsuspend_args *uap = v;
|
|
hpux_sigset_t sigset;
|
|
sigset_t mask;
|
|
int error;
|
|
|
|
error = copyin(SCARG(uap, set), &sigset, sizeof(sigset));
|
|
if (error)
|
|
return (error);
|
|
|
|
hpuxtobsdmask(sigset.sigset[0], &mask);
|
|
return (sigsuspend1(p, &mask));
|
|
}
|
|
|
|
int
|
|
hpux_sys_sigaction(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_sigaction_args *uap = v;
|
|
struct hpux_sigaction action;
|
|
struct hpux_sigaction *sa;
|
|
struct sigaction *bsa;
|
|
int sig, error;
|
|
|
|
sig = hpuxtobsdsig(SCARG(uap, signo));
|
|
if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
|
|
return (EINVAL);
|
|
|
|
bsa = &SIGACTION(p, sig);
|
|
|
|
sa = &action;
|
|
if (SCARG(uap, osa)) {
|
|
sa->sa_handler = bsa->sa_handler;
|
|
memset((caddr_t)&sa->sa_mask, 0, sizeof(sa->sa_mask));
|
|
bsdtohpuxmask(&bsa->sa_mask, &sa->sa_mask.sigset[0]);
|
|
sa->sa_flags = 0;
|
|
if (bsa->sa_flags & SA_ONSTACK)
|
|
sa->sa_flags |= HPUXSA_ONSTACK;
|
|
if (bsa->sa_flags & SA_RESETHAND)
|
|
sa->sa_flags |= HPUXSA_RESETHAND;
|
|
if (bsa->sa_flags & SA_NOCLDSTOP)
|
|
sa->sa_flags |= HPUXSA_NOCLDSTOP;
|
|
error = copyout(sa, SCARG(uap, osa), sizeof (action));
|
|
if (error)
|
|
return (error);
|
|
}
|
|
if (SCARG(uap, nsa)) {
|
|
struct sigaction act;
|
|
|
|
error = copyin(SCARG(uap, nsa), sa, sizeof(action));
|
|
if (error)
|
|
return (error);
|
|
if (sig == SIGCONT && sa->sa_handler == SIG_IGN)
|
|
return (EINVAL);
|
|
|
|
act.sa_handler = sa->sa_handler;
|
|
hpuxtobsdmask(sa->sa_mask.sigset[0], &act.sa_mask);
|
|
act.sa_flags = SA_RESTART;
|
|
if (sa->sa_flags & HPUXSA_ONSTACK)
|
|
act.sa_flags |= SA_ONSTACK;
|
|
if (sa->sa_flags & HPUXSA_RESETHAND)
|
|
act.sa_flags |= SA_RESETHAND;
|
|
if (sa->sa_flags & HPUXSA_NOCLDSTOP)
|
|
act.sa_flags |= SA_NOCLDSTOP;
|
|
|
|
error = sigaction1(p, sig, &act, NULL, NULL, 0);
|
|
if (error)
|
|
return (error);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
hpux_sys_ssig_6x(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct hpux_sys_ssig_6x_args /* {
|
|
syscallarg(int) signo;
|
|
syscallarg(sig_t) fun;
|
|
} */ *uap = v;
|
|
int a;
|
|
struct sigaction vec;
|
|
struct sigaction *sa = &vec;
|
|
|
|
memset(sa, 0, sizeof(*sa));
|
|
a = hpuxtobsdsig(SCARG(uap, signo));
|
|
sa->sa_handler = SCARG(uap, fun);
|
|
/*
|
|
* Kill processes trying to use job control facilities
|
|
* (this'll help us find any vestiges of the old stuff).
|
|
*/
|
|
if ((a &~ 0377) ||
|
|
(sa->sa_handler != SIG_DFL && sa->sa_handler != SIG_IGN &&
|
|
((int)sa->sa_handler) & 1)) {
|
|
psignal(p, SIGSYS);
|
|
return (0);
|
|
}
|
|
if (a <= 0 || a >= NSIG || a == SIGKILL || a == SIGSTOP ||
|
|
(a == SIGCONT && sa->sa_handler == SIG_IGN))
|
|
return (EINVAL);
|
|
sigemptyset(&sa->sa_mask);
|
|
sa->sa_flags = 0;
|
|
*retval = (register_t)SIGACTION(p, a).sa_handler;
|
|
sigaction1(p, a, sa, NULL, NULL, 0);
|
|
#if 0
|
|
p->p_flag |= SOUSIG; /* mark as simulating old stuff */
|
|
#endif
|
|
return (0);
|
|
}
|
|
|
|
/* signal numbers: convert from HPUX to BSD */
|
|
int
|
|
hpuxtobsdsig(sig)
|
|
int sig;
|
|
{
|
|
if (sig < 0 || sig >= NSIG)
|
|
return(0);
|
|
return hpux_to_native_signo[sig];
|
|
}
|
|
|
|
/* signal numbers: convert from BSD to HPUX */
|
|
int
|
|
bsdtohpuxsig(sig)
|
|
int sig;
|
|
{
|
|
if (sig < 0 || sig >= NSIG)
|
|
return(0);
|
|
return native_to_hpux_signo[sig];
|
|
}
|
|
|
|
/* signal masks: convert from HPUX to BSD (not pretty or fast) */
|
|
void
|
|
hpuxtobsdmask(hpuxmask, bsdmask)
|
|
int hpuxmask;
|
|
sigset_t *bsdmask;
|
|
{
|
|
int sig, nsig;
|
|
|
|
sigemptyset(bsdmask);
|
|
|
|
for (sig = 1; sig < NSIG; sig++) {
|
|
if ((hpuxmask & (1 << sig)) != 0 &&
|
|
(nsig = hpuxtobsdsig(sig)) != 0)
|
|
sigaddset(bsdmask, sig);
|
|
}
|
|
}
|
|
|
|
void
|
|
bsdtohpuxmask(bsdmask, hpuxmask)
|
|
const sigset_t *bsdmask;
|
|
int *hpuxmask;
|
|
{
|
|
int sig, nsig;
|
|
|
|
*hpuxmask = 0;
|
|
|
|
for (sig = 1; sig < NSIG; sig++) {
|
|
if (sigismember(bsdmask, sig) &&
|
|
(nsig = bsdtohpuxsig(sig)) != 0)
|
|
*hpuxmask |= (1 << sig);
|
|
}
|
|
}
|