BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / hp / hpux / hpux_sig.c
index 1aee2c9..8b788d4 100644 (file)
@@ -1,17 +1,43 @@
 /*
  * Copyright (c) 1988 University of Utah.
 /*
  * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
+ * 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.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  * Science Department.
  *
- * %sccs.include.redist.c%
+ * 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.
  *
  *
- * from: Utah $Hdr: hpux_compat.c 1.33 89/08/23$
+ * 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.
  *
  *
- *     @(#)hpux_sig.c  7.4 (Berkeley) %G%
+ * from: Utah $Hdr: hpux_sig.c 1.4 92/01/20$
+ *
+ *     @(#)hpux_sig.c  8.2 (Berkeley) 9/23/93
  */
 
 /*
  */
 
 /*
 
 #ifdef HPUXCOMPAT
 
 
 #ifdef HPUXCOMPAT
 
-#include "param.h"
-#include "systm.h"
-#include "user.h"
-#include "kernel.h"
-#include "proc.h"
-#include "hpux.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+
+#include <hp/hpux/hpux.h>
 
 /* indexed by HPUX signal number - 1 */
 char hpuxtobsdsigmap[NSIG] = {
 
 /* indexed by HPUX signal number - 1 */
 char hpuxtobsdsigmap[NSIG] = {
@@ -52,16 +79,18 @@ char bsdtohpuxsigmap[NSIG] = {
  * swell foop.  I suspect we can get away with this since I
  * doubt any program of interest mixes the two semantics.
  */
  * swell foop.  I suspect we can get away with this since I
  * doubt any program of interest mixes the two semantics.
  */
+struct hpuxsigvec_args {
+       int     signo;
+       struct  sigvec *nsv;
+       struct  sigvec *osv;
+};
 hpuxsigvec(p, uap, retval)
        struct proc *p;
 hpuxsigvec(p, uap, retval)
        struct proc *p;
-       register struct args {
-               int     signo;
-               struct  sigvec *nsv;
-               struct  sigvec *osv;
-       } *uap;
+       register struct hpuxsigvec_args *uap;
        int *retval;
 {
        struct sigvec vec;
        int *retval;
 {
        struct sigvec vec;
+       register struct sigacts *ps = p->p_sigacts;
        register struct sigvec *sv;
        register int sig;
        int bit, error;
        register struct sigvec *sv;
        register int sig;
        int bit, error;
@@ -71,13 +100,13 @@ hpuxsigvec(p, uap, retval)
                return (EINVAL);
        sv = &vec;
        if (uap->osv) {
                return (EINVAL);
        sv = &vec;
        if (uap->osv) {
-               sv->sv_handler = u.u_signal[sig];
-               sv->sv_mask = u.u_sigmask[sig];
+               sv->sv_handler = ps->ps_sigact[sig];
+               sv->sv_mask = ps->ps_catchmask[sig];
                bit = sigmask(sig);
                sv->sv_flags = 0;
                bit = sigmask(sig);
                sv->sv_flags = 0;
-               if ((u.u_sigonstack & bit) != 0)
+               if ((ps->ps_sigonstack & bit) != 0)
                        sv->sv_flags |= SV_ONSTACK;
                        sv->sv_flags |= SV_ONSTACK;
-               if ((u.u_sigintr & bit) != 0)
+               if ((ps->ps_sigintr & bit) != 0)
                        sv->sv_flags |= SV_INTERRUPT;
 #if 0
 /* XXX -- SOUSIG no longer exists, do something here */
                        sv->sv_flags |= SV_INTERRUPT;
 #if 0
 /* XXX -- SOUSIG no longer exists, do something here */
@@ -94,6 +123,7 @@ hpuxsigvec(p, uap, retval)
                        return (error);
                if (sig == SIGCONT && sv->sv_handler == SIG_IGN)
                        return (EINVAL);
                        return (error);
                if (sig == SIGCONT && sv->sv_handler == SIG_IGN)
                        return (EINVAL);
+               sv->sv_flags ^= SA_RESTART;
                setsigvec(p, sig, (struct sigaction *)sv);
 #if 0
 /* XXX -- SOUSIG no longer exists, do something here */
                setsigvec(p, sig, (struct sigaction *)sv);
 #if 0
 /* XXX -- SOUSIG no longer exists, do something here */
@@ -104,11 +134,12 @@ hpuxsigvec(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
+struct hpuxsigblock_args {
+       int     mask;
+};
 hpuxsigblock(p, uap, retval)
        register struct proc *p;
 hpuxsigblock(p, uap, retval)
        register struct proc *p;
-       struct args {
-               int     mask;
-       } *uap;
+       struct hpuxsigblock_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -119,11 +150,12 @@ hpuxsigblock(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
+struct hpuxsigsetmask_args {
+       int     mask;
+};
 hpuxsigsetmask(p, uap, retval)
        struct proc *p;
 hpuxsigsetmask(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     mask;
-       } *uap;
+       struct hpuxsigsetmask_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -134,11 +166,12 @@ hpuxsigsetmask(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
+struct hpuxsigpause_args {
+       int     mask;
+};
 hpuxsigpause(p, uap, retval)
        struct proc *p;
 hpuxsigpause(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     mask;
-       } *uap;
+       struct hpuxsigpause_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -147,12 +180,13 @@ hpuxsigpause(p, uap, retval)
 }
 
 /* not totally correct, but close enuf' */
 }
 
 /* not totally correct, but close enuf' */
+struct hpuxkill_args {
+       int     pid;
+       int     signo;
+};
 hpuxkill(p, uap, retval)
        struct proc *p;
 hpuxkill(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     pid;
-               int     signo;
-       } *uap;
+       struct hpuxkill_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -164,42 +198,207 @@ hpuxkill(p, uap, retval)
        return (kill(p, uap, retval));
 }
 
        return (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.
+ */
+struct hpuxsigprocmask_args {
+       int             how;
+       hpuxsigset_t    *set;
+       hpuxsigset_t    *oset;
+};
+hpuxsigprocmask(p, uap, retval)
+       register struct proc *p;
+       struct hpuxsigprocmask_args *uap;
+       int *retval;
+{
+       int mask, error = 0;
+       hpuxsigset_t sigset;
+
+       /*
+        * Copy out old mask first to ensure no errors.
+        * (proc sigmask should not be changed if call fails for any reason)
+        */
+       if (uap->oset) {
+               bzero((caddr_t)&sigset, sizeof(sigset));
+               sigset.sigset[0] = bsdtohpuxmask(p->p_sigmask);
+               if (copyout((caddr_t)&sigset, (caddr_t)uap->oset, sizeof(sigset)))
+                       return (EFAULT);
+       }
+       if (uap->set) {
+               if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset)))
+                       return (EFAULT);
+               mask = hpuxtobsdmask(sigset.sigset[0]);
+               (void) splhigh();
+               switch (uap->how) {
+               case HPUXSIG_BLOCK:
+                       p->p_sigmask |= mask &~ sigcantmask;
+                       break;
+               case HPUXSIG_UNBLOCK:
+                       p->p_sigmask &= ~mask;
+                       break;
+               case HPUXSIG_SETMASK:
+                       p->p_sigmask = mask &~ sigcantmask;
+                       break;
+               default:
+                       error = EINVAL;
+                       break;
+               }
+               (void) spl0();
+       }
+       return (error);
+}
+
+struct hpuxsigpending_args {
+       hpuxsigset_t    *set;
+};
+hpuxsigpending(p, uap, retval)
+       register struct proc *p;
+       struct hpuxsigpending_args *uap;
+       int *retval;
+{
+       hpuxsigset_t sigset;
+
+       sigset.sigset[0] = bsdtohpuxmask(p->p_siglist);
+       return (copyout((caddr_t)&sigset, (caddr_t)uap->set, sizeof(sigset)));
+}
+
+struct hpuxsigsuspend_args {
+       hpuxsigset_t    *set;
+};
+hpuxsigsuspend(p, uap, retval)
+       register struct proc *p;
+       struct hpuxsigsuspend_args *uap;
+       int *retval;
+{
+       register struct sigacts *ps = p->p_sigacts;
+       hpuxsigset_t sigset;
+       int mask;
+
+       if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset)))
+               return (EFAULT);
+       mask = hpuxtobsdmask(sigset.sigset[0]);
+       ps->ps_oldmask = p->p_sigmask;
+       ps->ps_flags |= SAS_OLDMASK;
+       p->p_sigmask = mask &~ sigcantmask;
+       (void) tsleep((caddr_t)ps, PPAUSE | PCATCH, "pause", 0);
+       /* always return EINTR rather than ERESTART... */
+       return (EINTR);
+}
+
+struct hpuxsigaction_args {
+       int     signo;
+       struct  hpuxsigaction *nsa;
+       struct  hpuxsigaction *osa;
+};
+hpuxsigaction(p, uap, retval)
+       struct proc *p;
+       register struct hpuxsigaction_args *uap;
+       int *retval;
+{
+       struct hpuxsigaction action;
+       register struct sigacts *ps = p->p_sigacts;
+       register struct hpuxsigaction *sa;
+       register int sig;
+       int bit;
+
+       sig = hpuxtobsdsig(uap->signo);
+       if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
+               return (EINVAL);
+
+       sa = &action;
+       if (uap->osa) {
+               sa->sa_handler = ps->ps_sigact[sig];
+               bzero((caddr_t)&sa->sa_mask, sizeof(sa->sa_mask));
+               sa->sa_mask.sigset[0] = bsdtohpuxmask(ps->ps_catchmask[sig]);
+               bit = sigmask(sig);
+               sa->sa_flags = 0;
+               if ((ps->ps_sigonstack & bit) != 0)
+                       sa->sa_flags |= HPUXSA_ONSTACK;
+#if 0
+/* XXX -- SOUSIG no longer exists, do something here */
+               if (p->p_flag & SOUSIG)
+                       sa->sa_flags |= HPUXSA_RESETHAND;       /* XXX */
+#endif
+               if (p->p_flag & P_NOCLDSTOP)
+                       sa->sa_flags |= HPUXSA_NOCLDSTOP;
+               if (copyout((caddr_t)sa, (caddr_t)uap->osa, sizeof (action)))
+                       return (EFAULT);
+       }
+       if (uap->nsa) {
+               struct sigaction act;
+
+               if (copyin((caddr_t)uap->nsa, (caddr_t)sa, sizeof (action)))
+                       return (EFAULT);
+               if (sig == SIGCONT && sa->sa_handler == SIG_IGN)
+                       return (EINVAL);
+               /*
+                * Create a sigaction struct for setsigvec
+                */
+               act.sa_handler = sa->sa_handler;
+               act.sa_mask = hpuxtobsdmask(sa->sa_mask.sigset[0]);
+               act.sa_flags == SA_RESTART;
+               if (sa->sa_flags & HPUXSA_ONSTACK)
+                       act.sa_flags |= SA_ONSTACK;
+               if (sa->sa_flags & HPUXSA_NOCLDSTOP)
+                       act.sa_flags |= SA_NOCLDSTOP;
+               setsigvec(p, sig, &act);
+#if 0
+/* XXX -- SOUSIG no longer exists, do something here */
+               if (sa->sa_flags & HPUXSA_RESETHAND)
+                       p->p_flag |= SOUSIG;            /* XXX */
+#endif
+       }
+       return (0);
+}
+
+#ifdef COMPAT_OHPUX
+struct ohpuxssig_args {
+       int     signo;
+       sig_t   fun;
+};
 ohpuxssig(p, uap, retval)
        struct proc *p;
 ohpuxssig(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     signo;
-               sig_t   fun;
-       } *uap;
+       struct ohpuxssig_args *uap;
        int *retval;
 {
        register int a;
        int *retval;
 {
        register int a;
-       struct sigvec vec;
-       register struct sigvec *sv = &vec;
+       struct sigaction vec;
+       register struct sigaction *sa = &vec;
 
        a = hpuxtobsdsig(uap->signo);
 
        a = hpuxtobsdsig(uap->signo);
-       sv->sv_handler = uap->fun;
+       sa->sa_handler = uap->fun;
        /*
         * Kill processes trying to use job control facilities
         * (this'll help us find any vestiges of the old stuff).
         */
        if ((a &~ 0377) ||
        /*
         * Kill processes trying to use job control facilities
         * (this'll help us find any vestiges of the old stuff).
         */
        if ((a &~ 0377) ||
-           (sv->sv_handler != SIG_DFL && sv->sv_handler != SIG_IGN &&
-            ((int)sv->sv_handler) & 1)) {
+           (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 ||
                psignal(p, SIGSYS);
                return (0);
        }
        if (a <= 0 || a >= NSIG || a == SIGKILL || a == SIGSTOP ||
-           a == SIGCONT && sv->sv_handler == SIG_IGN)
+           a == SIGCONT && sa->sa_handler == SIG_IGN)
                return (EINVAL);
                return (EINVAL);
-       sv->sv_mask = 0;
-       sv->sv_flags = SV_INTERRUPT;
-       *retval = (int)u.u_signal[a];
-       setsigvec(p, a, (struct sigaction *)sv);
+       sa->sa_mask = 0;
+       sa->sa_flags = 0;
+       *retval = (int)p->p_sigacts->ps_sigact[a];
+       setsigvec(p, a, sa);
 #if 0
        p->p_flag |= SOUSIG;            /* mark as simulating old stuff */
 #endif
        return (0);
 }
 #if 0
        p->p_flag |= SOUSIG;            /* mark as simulating old stuff */
 #endif
        return (0);
 }
+#endif
 
 /* signal numbers: convert from HPUX to BSD */
 hpuxtobsdsig(sig)
 
 /* signal numbers: convert from HPUX to BSD */
 hpuxtobsdsig(sig)