Implement rt_sigaction, rt_sigprocmask, rt_sigpending & rt_sigsuspend.
authorjasoni <jasoni@openbsd.org>
Mon, 13 Mar 2000 08:18:30 +0000 (08:18 +0000)
committerjasoni <jasoni@openbsd.org>
Mon, 13 Mar 2000 08:18:30 +0000 (08:18 +0000)
sys/compat/linux/linux_signal.c
sys/compat/linux/syscalls.master

index e85d296..ee9c499 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: linux_signal.c,v 1.5 2000/03/08 03:35:28 jasoni Exp $ */
+/*     $OpenBSD: linux_signal.c,v 1.6 2000/03/13 08:18:30 jasoni Exp $ */
 /*     $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $       */
 
 /*
@@ -413,6 +413,68 @@ linux_sys_sigaction(p, v, retval)
        return 0;
 }
 
+int
+linux_sys_rt_sigaction(p, v, retval)
+       register struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct linux_sys_rt_sigaction_args /* {
+               syscallarg(int) signum;
+               syscallarg(struct linux_sigaction *) nsa;
+               syscallarg(struct linux_sigaction *) osa;
+               syscallarg(size_t) sigsetsize;
+       } */ *uap = v;
+       struct linux_sigaction *nlsa, *olsa, tmplsa;
+       struct sigaction *nbsa, *obsa, tmpbsa;
+       struct sys_sigaction_args sa;
+       caddr_t sg;
+       int error;
+
+       if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
+               return (EINVAL);
+
+       if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX_NSIG)
+               return (EINVAL);
+
+       sg = stackgap_init(p->p_emul);
+       nlsa = SCARG(uap, nsa);
+       olsa = SCARG(uap, osa);
+
+       if (olsa != NULL) 
+               obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+       else
+               obsa = NULL;
+
+       if (nlsa != NULL) {
+               nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+               if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
+                       return error;
+               linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
+               if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
+                       return error;
+       }
+       else
+               nbsa = NULL;
+
+       SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
+       SCARG(&sa, nsa) = nbsa;
+       SCARG(&sa, osa) = obsa;
+
+       if ((error = sys_sigaction(p, &sa, retval)) != 0)
+               return error;
+
+       if (olsa != NULL) {
+               if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
+                       return error;
+               bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
+               if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
+                       return error;
+       }
+
+       return 0;
+}
+
 /*
  * The Linux signal() system call. I think that the signal() in the C
  * library actually calls sigaction, so I doubt this one is ever used.
@@ -521,6 +583,68 @@ linux_sys_sigprocmask(p, v, retval)
        return error;
 }
 
+int
+linux_sys_rt_sigprocmask(p, v, retval)
+       register struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct linux_sys_rt_sigprocmask_args /* {
+               syscallarg(int) how;
+               syscallarg(const linux_sigset_t *) set;
+               syscallarg(linux_sigset_t *) oset;
+               syscallarg(size_t) sigsetsize;
+       } */ *uap = v;
+       linux_sigset_t ls;
+       sigset_t bs;
+       int error = 0;
+
+       if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
+               return (EINVAL);
+
+       *retval = 0;
+
+       if (SCARG(uap, oset) != NULL) {
+               /* Fix the return value first if needed */
+               bsd_to_linux_sigset(&p->p_sigmask, &ls);
+               if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
+                       return error;
+       }
+
+       if (SCARG(uap, set) == NULL)
+               /* Just examine */
+               return 0;
+
+       if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
+               return error;
+
+       linux_to_bsd_sigset(&ls, &bs);
+
+       (void) splhigh();
+
+       switch (SCARG(uap, how)) {
+       case LINUX_SIG_BLOCK:
+               p->p_sigmask |= bs & ~sigcantmask;
+               break;
+
+       case LINUX_SIG_UNBLOCK:
+               p->p_sigmask &= ~bs;
+               break;
+
+       case LINUX_SIG_SETMASK:
+               p->p_sigmask = bs & ~sigcantmask;
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       (void) spl0();
+
+       return error;
+}
+
 /*
  * The functions below really make no distinction between an int
  * and [linux_]sigset_t. This is ok for now, but it might break
@@ -587,6 +711,28 @@ linux_sys_sigpending(p, v, retval)
        return copyout(&ls, SCARG(uap, mask), sizeof(ls));
 }
 
+int
+linux_sys_rt_sigpending(p, v, retval)
+       register struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct linux_sys_rt_sigpending_args /* {
+               syscallarg(linux_sigset_t *) set;
+               syscallarg(size_t) sigsetsize;
+       } */ *uap = v;
+       sigset_t bs;
+       linux_sigset_t ls;
+
+       if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
+               return (EINVAL);
+
+       bs = p->p_siglist & p->p_sigmask;
+       bsd_to_linux_sigset(&bs, &ls);
+
+       return copyout(&ls, SCARG(uap, set), sizeof(ls));
+}
+
 int
 linux_sys_sigsuspend(p, v, retval)
        register struct proc *p;
@@ -605,6 +751,31 @@ linux_sys_sigsuspend(p, v, retval)
        return sys_sigsuspend(p, &sa, retval);
 }
 
+int
+linux_sys_rt_sigsuspend(p, v, retval)
+       register struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct linux_sys_rt_sigsuspend_args /* {
+               syscallarg(sigset_t *) unewset;
+               syscallarg(size_t) sigsetsize;
+       } */ *uap = v;
+       struct sys_sigsuspend_args sa;
+       linux_sigset_t mask;
+       int error;
+
+       if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
+               return (EINVAL);
+       
+       error = copyin(SCARG(uap, unewset), &mask, sizeof(linux_sigset_t));
+       if (error)
+               return (error);
+       
+       linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
+       return sys_sigsuspend(p, &sa, retval);
+}
+
 /*
  * The deprecated pause(2), which is really just an instance
  * of sigsuspend(2).
index 3831889..6c779a9 100644 (file)
@@ -1,4 +1,4 @@
-       $OpenBSD: syscalls.master,v 1.16 2000/03/08 03:35:29 jasoni Exp $
+       $OpenBSD: syscalls.master,v 1.17 2000/03/13 08:18:30 jasoni Exp $
 ;      $NetBSD: syscalls.master,v 1.15 1995/12/18 14:35:10 fvdl Exp $
 
 ;      @(#)syscalls.master     8.1 (Berkeley) 7/19/93
                            gid_t *sgid); }
 172    UNIMPL          prctl
 173    UNIMPL          rt_sigreturn
-174    UNIMPL          rt_sigaction
-175    UNIMPL          rt_sigprocmask
-176    UNIMPL          rt_sigpending
+174    STD             { int linux_sys_rt_sigaction(int signum, \
+                           struct linux_sigaction *nsa, \
+                           struct linux_sigaction *osa, \
+                           size_t sigsetsize); }
+175    STD             { int linux_sys_rt_sigprocmask(int how, \
+                           const linux_sigset_t *set, \
+                           linux_sigset_t *oset, size_t sigsetsize); }
+176    STD             { int linux_sys_rt_sigpending(linux_sigset_t *set, \
+                           size_t sigsetsize); }
 177    UNIMPL          rt_sigtimedwait
 178    UNIMPL          rt_queueinfo
-179    UNIMPL          rt_sigsuspend
+179    STD             { int linux_sys_rt_sigsuspend(linux_sigset_t *unewset, \
+                           size_t sigsetsize); }
 180    UNIMPL          pread
 181    UNIMPL          pwrite
 182    STD             { int linux_sys_chown(char *path, int uid, int gid); }