diff options
Diffstat (limited to 'sys/i386/linux/linux_signal.c')
-rw-r--r-- | sys/i386/linux/linux_signal.c | 210 |
1 files changed, 130 insertions, 80 deletions
diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c index fc5c2cd..32648cb 100644 --- a/sys/i386/linux/linux_signal.c +++ b/sys/i386/linux/linux_signal.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_signal.c,v 1.2 1995/11/22 07:43:50 bde Exp $ + * $Id: linux_signal.c,v 1.3 1995/12/15 03:06:56 peter Exp $ */ #include <sys/param.h> @@ -37,69 +37,96 @@ #include <sys/signalvar.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> - -#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD)) +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> static sigset_t -linux_to_bsd_sigmask(linux_sigset_t mask) { - int i; +linux_to_bsd_sigset(linux_sigset_t mask) { + int b, l; sigset_t new = 0; - for (i = 1; i <= LINUX_NSIG; i++) - if (mask & (1 << i-1)) - new |= (1 << (linux_to_bsd_signal[i]-1)); + for (l = 1; l <= LINUX_NSIG; l++) { + if (mask & (1 << (l - 1))) { + if ((b = linux_to_bsd_signal[l])) + new |= (1 << (b - 1)); + } + } return new; } static linux_sigset_t -bsd_to_linux_sigmask(sigset_t mask) { - int i; +bsd_to_linux_sigset(sigset_t mask) { + int b, l; sigset_t new = 0; - for (i = 1; i <= NSIG; i++) - if (mask & (1 << i-1)) - new |= (1 << (bsd_to_linux_signal[i]-1)); + for (b = 1; b <= NSIG; b++) { + if (mask & (1 << (b - 1))) { + if ((l = bsd_to_linux_signal[b])) + new |= (1 << (l - 1)); + } + } return new; } -struct linux_sigaction_args { - int sig; - linux_sigaction_t *nsa; - linux_sigaction_t *osa; -}; +void +linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) +{ + bsa->sa_mask = linux_to_bsd_sigset(lsa->sa_mask); + bsa->sa_handler = lsa->sa_handler; + bsa->sa_flags = 0; + if (lsa->sa_flags & LINUX_SA_NOCLDSTOP) + bsa->sa_flags |= SA_NOCLDSTOP; + if (lsa->sa_flags & LINUX_SA_ONSTACK) + bsa->sa_flags |= SA_ONSTACK; + if (lsa->sa_flags & LINUX_SA_RESTART) + bsa->sa_flags |= SA_RESTART; + if (lsa->sa_flags & LINUX_SA_ONESHOT) + bsa->sa_flags |= SA_RESETHAND; + if (lsa->sa_flags & LINUX_SA_NOMASK) + bsa->sa_flags |= SA_NODEFER; +} + +void +bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) +{ + lsa->sa_handler = bsa->sa_handler; + lsa->sa_restorer = NULL; /* unsupported */ + lsa->sa_mask = bsd_to_linux_sigset(bsa->sa_mask); + lsa->sa_flags = 0; + if (bsa->sa_flags & SA_NOCLDSTOP) + lsa->sa_flags |= LINUX_SA_NOCLDSTOP; + if (bsa->sa_flags & SA_ONSTACK) + lsa->sa_flags |= LINUX_SA_ONSTACK; + if (bsa->sa_flags & SA_RESTART) + lsa->sa_flags |= LINUX_SA_RESTART; + if (bsa->sa_flags & SA_RESETHAND) + lsa->sa_flags |= LINUX_SA_ONESHOT; + if (bsa->sa_flags & SA_NODEFER) + lsa->sa_flags |= LINUX_SA_NOMASK; +} int linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval) { linux_sigaction_t linux_sa; struct sigaction *nsa = NULL, *osa = NULL, bsd_sa; - struct sigaction_args /* { - int signum; - struct sigaction *nsa; - struct sigaction *osa; - } */ sa; + struct sigaction_args sa; int error; + caddr_t sg = stackgap_init(); #ifdef DEBUG - printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig); + printf("Linux-emul(%d): sigaction(%d, %08x, %08x)\n", p->p_pid, args->sig, + args->nsa, args->osa); #endif + if (args->osa) - osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction)); + osa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction)); if (args->nsa) { - nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction)); + nsa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction)); if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t))) return error; - bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask); - bsd_sa.sa_handler = linux_sa.sa_handler; - bsd_sa.sa_flags = 0; - if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP) - bsd_sa.sa_flags |= SA_NOCLDSTOP; - if (linux_sa.sa_flags & LINUX_SA_ONSTACK) - bsd_sa.sa_flags |= SA_ONSTACK; - if (linux_sa.sa_flags & LINUX_SA_RESTART) - bsd_sa.sa_flags |= SA_RESTART; + linux_to_bsd_sigaction(&linux_sa, &bsd_sa); if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction))) return error; } @@ -112,27 +139,49 @@ linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval) if (args->osa) { if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction))) return error; - linux_sa.sa_handler = bsd_sa.sa_handler; - linux_sa.sa_restorer = NULL; - linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask); - linux_sa.sa_flags = 0; - if (bsd_sa.sa_flags & SA_NOCLDSTOP) - linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP; - if (bsd_sa.sa_flags & SA_ONSTACK) - linux_sa.sa_flags |= LINUX_SA_ONSTACK; - if (bsd_sa.sa_flags & SA_RESTART) - linux_sa.sa_flags |= LINUX_SA_RESTART; + bsd_to_linux_sigaction(&bsd_sa, &linux_sa); if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t))) return error; } return 0; } -struct linux_sigprocmask_args { - int how; - linux_sigset_t *mask; - linux_sigset_t *omask; -}; +int +linux_signal(struct proc *p, struct linux_signal_args *args, int *retval) +{ + caddr_t sg; + struct sigaction_args sa_args; + struct sigaction *osa, *nsa, tmpsa; + int error; + +#ifdef DEBUG + printf("Linux-emul(%d): signal(%d, %08x)\n", p->p_pid, + args->sig, args->handler); +#endif + sg = stackgap_init(); + nsa = stackgap_alloc(&sg, sizeof *nsa); + osa = stackgap_alloc(&sg, sizeof *osa); + + tmpsa.sa_handler = args->handler; + tmpsa.sa_mask = (sigset_t) 0; + tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER; + if ((error = copyout(&tmpsa, nsa, sizeof tmpsa))) + return error; + + sa_args.signum = linux_to_bsd_signal[args->sig]; + sa_args.osa = osa; + sa_args.nsa = nsa; + if ((error = sigaction(p, &sa_args, retval))) + return error; + + if ((error = copyin(osa, &tmpsa, sizeof *osa))) + return error; + + *retval = (int)tmpsa.sa_handler; + + return 0; +} + int linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, @@ -145,8 +194,11 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, #ifdef DEBUG printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how); #endif + + *retval = 0; + if (args->omask != NULL) { - omask = bsd_to_linux_sigmask(p->p_sigmask); + omask = bsd_to_linux_sigset(p->p_sigmask); if (error = copyout(&omask, args->omask, sizeof(sigset_t))) return error; } @@ -155,17 +207,17 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t))) return error; - mask = linux_to_bsd_sigmask(mask); + mask = linux_to_bsd_sigset(mask); s = splhigh(); switch (args->how) { case LINUX_SIG_BLOCK: - p->p_sigmask |= (mask & ~DONTMASK); + p->p_sigmask |= (mask & ~sigcantmask); break; case LINUX_SIG_UNBLOCK: p->p_sigmask &= ~mask; break; case LINUX_SIG_SETMASK: - p->p_sigmask = (mask & ~DONTMASK); + p->p_sigmask = (mask & ~sigcantmask); break; default: error = EINVAL; @@ -176,38 +228,33 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, } int -linux_siggetmask(struct proc *p, void *args, int *retval) +linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args, int *retval) { #ifdef DEBUG printf("Linux-emul(%d): siggetmask()\n", p->p_pid); #endif - *retval = bsd_to_linux_sigmask(p->p_sigmask); + *retval = bsd_to_linux_sigset(p->p_sigmask); return 0; } -struct linux_sigsetmask_args { - linux_sigset_t mask; -}; - int linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval) { int s; + sigset_t mask; #ifdef DEBUG printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask); #endif + *retval = bsd_to_linux_sigset(p->p_sigmask); + + mask = linux_to_bsd_sigset(args->mask); s = splhigh(); - p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK); + p->p_sigmask = mask & ~sigcantmask; splx(s); - *retval = bsd_to_linux_sigmask(p->p_sigmask); return 0; } -struct linux_sigpending_args { - linux_sigset_t *mask; -}; - int linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval) { @@ -216,32 +263,35 @@ linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval) #ifdef DEBUG printf("Linux-emul(%d): sigpending(*)\n", p->p_pid); #endif - linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask); + linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask); return copyout(&linux_sig, args->mask, sizeof(linux_sig)); } -struct linux_sigsuspend_args { - linux_sigset_t mask; -}; - int linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval) { - struct sigsuspend_args /* { - int mask; - } */ tmp; + struct sigsuspend_args tmp; + int error; #ifdef DEBUG printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask); #endif - tmp.mask = linux_to_bsd_sigmask(args->mask); + tmp.mask = linux_to_bsd_sigset(args->mask); return sigsuspend(p, &tmp , retval); } -struct linux_kill_args { - int pid; - int signum; -}; +int +linux_pause(struct proc *p, struct linux_pause_args *args,int *retval) +{ + struct sigsuspend_args tmp; + int error; + +#ifdef DEBUG + printf("Linux-emul(%d): pause()\n", p->p_pid); +#endif + tmp.mask = p->p_sigmask; + return sigsuspend(p, &tmp , retval); +} int linux_kill(struct proc *p, struct linux_kill_args *args, int *retval) |