diff options
-rw-r--r-- | sys/compat/linux/linux_signal.c | 173 | ||||
-rw-r--r-- | sys/compat/linux/syscalls.master | 17 |
2 files changed, 184 insertions, 6 deletions
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index e85d2969e06..ee9c499fc34 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -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 @@ -588,6 +712,28 @@ linux_sys_sigpending(p, v, retval) } 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; void *v; @@ -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). diff --git a/sys/compat/linux/syscalls.master b/sys/compat/linux/syscalls.master index 3831889c329..6c779a99d7a 100644 --- a/sys/compat/linux/syscalls.master +++ b/sys/compat/linux/syscalls.master @@ -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 @@ -276,12 +276,19 @@ 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); } |