summaryrefslogtreecommitdiffstats
path: root/sys/i386/ibcs2/ibcs2_signal.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>1994-10-14 08:53:16 +0000
committersos <sos@FreeBSD.org>1994-10-14 08:53:16 +0000
commit8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef (patch)
tree03e7e36f42559e1855d7488025f88b38a06ded17 /sys/i386/ibcs2/ibcs2_signal.c
parente5a7fbf2bb8340c56fa8524e8b92c32ee9abb588 (diff)
downloadFreeBSD-src-8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef.zip
FreeBSD-src-8c25a4d2ace95c98887a2c73b1a1b7ac8c79f8ef.tar.gz
iBCS2 emulator core files.
This is the main files for the iBCS2 emulator. It can be use compiled into the kernel by using: options IBCS2 options COMPAT_IBCS2 or as a lkm module using: options COMPAT_IBCS2 and then loading it via the ibcs2 script in /usr/bin REMEMBER: this code is still experimental ! NO WARRENTY ! Submitted by: sef@kithrup.com, mostyn@mrl.com, sos@kmd-ac.dk
Diffstat (limited to 'sys/i386/ibcs2/ibcs2_signal.c')
-rw-r--r--sys/i386/ibcs2/ibcs2_signal.c462
1 files changed, 462 insertions, 0 deletions
diff --git a/sys/i386/ibcs2/ibcs2_signal.c b/sys/i386/ibcs2/ibcs2_signal.c
new file mode 100644
index 0000000..7824a0b
--- /dev/null
+++ b/sys/i386/ibcs2/ibcs2_signal.c
@@ -0,0 +1,462 @@
+/*-
+ * Copyright (c) 1994 Sean Eric Fagan
+ * Copyright (c) 1994 Søren Schmidt
+ * All rights reserved.
+ *
+ * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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
+ * in this position and unchanged.
+ * 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.
+ *
+ * $Id: ibcs2_signal.c,v 1.9 1994/10/12 19:38:03 sos Exp $
+ */
+
+#include <i386/ibcs2/ibcs2.h>
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/namei.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/vnode.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_map.h>
+#include <vm/vm_kern.h>
+
+
+#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
+
+int bsd_to_ibcs2_signal[NSIG] = {
+ 0, IBCS2_SIGHUP, IBCS2_SIGINT, IBCS2_SIGQUIT,
+ IBCS2_SIGILL, IBCS2_SIGTRAP, IBCS2_SIGABRT, IBCS2_SIGEMT,
+ IBCS2_SIGFPE, IBCS2_SIGKILL, IBCS2_SIGBUS, IBCS2_SIGSEGV,
+ IBCS2_SIGSYS, IBCS2_SIGPIPE, IBCS2_SIGALRM, IBCS2_SIGTERM,
+ IBCS2_SIGURG, IBCS2_SIGSTOP, IBCS2_SIGTSTP, IBCS2_SIGCONT,
+ IBCS2_SIGCHLD, IBCS2_SIGTTIN, IBCS2_SIGTTOU, IBCS2_SIGIO,
+ IBCS2_SIGGXCPU, IBCS2_SIGGXFSZ, IBCS2_SIGVTALRM, IBCS2_SIGPROF,
+ IBCS2_SIGWINCH, 0, IBCS2_SIGUSR1, IBCS2_SIGUSR2
+};
+
+int ibcs2_to_bsd_signal[IBCS2_NSIG] = {
+ 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
+ SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM, SIGTERM,
+ SIGUSR1, SIGUSR2, SIGCHLD, 0, SIGWINCH, SIGURG, SIGIO, SIGSTOP,
+ SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ
+};
+
+static char ibcs2_sig_name[IBCS2_NSIG][10] = {
+ "UNKNOWN", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP",
+ "SIGABRT", "SIGEMT", "SIGFPE", "SIGKILL", "SIGBUS", "SIGSEGV",
+ "SIGSYS", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGUSR1", "SIGUSR2",
+ "SIGCHLD", "SIGPWR", "SIGWINCH", "SIGURG", "SIGIO", "SIGSTOP",
+ "SIGTSTP", "SIGCONT", "SIGTTIN", "SIGTTOU", "SIGVTALRM",
+ "SIGPROF", "SIGXCPU", "SIGXFSZ"
+};
+
+/*#define LEGAL_SIG(x) \
+ (((x & IBCS2_SIGMASK) < IBCS2_NSIG) ? (x & IBCS2_SIGMASK) : (0))*/
+int
+LEGAL_SIG(int sig)
+{
+ if ((sig & IBCS2_SIGMASK) > IBCS2_NSIG) {
+ printf("IBCS2: illegal ibcs2 signal %d(%08x)\n",
+ sig & IBCS2_SIGMASK, sig);
+ return 0;
+ }
+ else
+ return (sig & IBCS2_SIGMASK);
+}
+
+char *
+ibcs2_sig_to_str(int sig)
+{
+ if (sig > IBCS2_NSIG) {
+ printf("IBCS2: ibcs2 signal out of range (%d)\n", sig);
+ return ibcs2_sig_name[0];
+ }
+ else
+ return ibcs2_sig_name[sig];
+}
+
+static sig_t
+ibcs2_to_bsd_sigfunc(ibcs2_sig_t func) {
+ switch ((int)func) {
+ case IBCS2_SIG_DFL:
+ return SIG_DFL;
+ case IBCS2_SIG_IGN:
+ return SIG_IGN;
+ case IBCS2_SIG_HOLD:
+ return SIG_HOLD;
+ default:
+ return func;
+ }
+}
+
+static ibcs2_sig_t
+bsd_to_ibcs2_sigfunc(sig_t func) {
+ switch ((int)func) {
+ case SIG_DFL:
+ return IBCS2_SIG_DFL;
+ case SIG_IGN:
+ return IBCS2_SIG_IGN;
+ case SIG_CATCH:
+ printf("IBCS2: Oops - SIG_CATCH does not translate :-(\n");
+ return IBCS2_SIG_DFL;
+ case SIG_HOLD:
+ return IBCS2_SIG_HOLD;
+ default:
+ return func;
+ }
+}
+
+static sigset_t
+ibcs2_to_bsd_sigmask(ibcs2_sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i < NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (ibcs2_to_bsd_signal[i]-1));
+ return new;
+}
+
+static ibcs2_sigset_t
+bsd_to_ibcs2_sigmask(sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i < IBCS2_NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (bsd_to_ibcs2_signal[i]-1));
+ return new;
+}
+
+struct ibcs2_signal_args {
+ int signo;
+ ibcs2_sig_t func;
+};
+
+static int
+ibcs2_sigset(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ struct sigaction tmp;
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ *retval = (int)bsd_to_ibcs2_sigfunc(p->p_sigacts->ps_sigact[sig_bsd]);
+ if (args->func == IBCS2_SIG_HOLD) {
+ (void) splhigh();
+ p->p_sigmask |= (sigmask(sig_bsd) &~ DONTMASK);
+ (void) spl0();
+ }
+ else {
+ tmp.sa_mask = sigmask(sig_bsd);
+ tmp.sa_handler = ibcs2_to_bsd_sigfunc(args->func);
+ tmp.sa_flags = 0;
+ setsigvec(p, sig_bsd, &tmp);
+ }
+ return 0;
+}
+
+static int
+ibcs2_sighold(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ (void) splhigh();
+ *retval = p->p_sigmask;
+ p->p_sigmask |= (sigmask(sig_bsd) & ~DONTMASK);
+ (void) spl0();
+ return 0;
+}
+
+static int
+ibcs2_sigrelse(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ (void) splhigh();
+ *retval = p->p_sigmask;
+ p->p_sigmask &= ~sigmask(sig_bsd);
+ (void) spl0();
+ return 0;
+}
+
+static int
+ibcs2_sigignore(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ struct sigaction tmp;
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ tmp.sa_mask = sigmask(sig_bsd);
+ tmp.sa_handler = SIG_IGN;
+ tmp.sa_flags = 0;
+ *retval = (int)bsd_to_ibcs2_sigfunc(p->p_sigacts->ps_sigact[sig_bsd]);
+ setsigvec(p, sig_bsd, &tmp);
+ return 0;
+}
+
+static int
+ibcs2_sigpause(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ struct sigacts *ps = p->p_sigacts;
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ ps->ps_oldmask = p->p_sigmask;
+ ps->ps_flags |= SAS_OLDMASK;
+ p->p_sigmask = sigmask(sig_bsd) &~ DONTMASK;
+ (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "i-pause", 0);
+ *retval = -1;
+ return EINTR;
+}
+
+static int
+ibcs2_signal(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ struct sigaction tmp;
+ int sig_bsd = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+
+ tmp.sa_mask = sigmask(sig_bsd);
+ tmp.sa_handler = ibcs2_to_bsd_sigfunc(args->func);
+ tmp.sa_flags = 0;
+ *retval = (int)bsd_to_ibcs2_sigfunc(p->p_sigacts->ps_sigact[sig_bsd]);
+ setsigvec(p, sig_bsd, &tmp);
+ return 0;
+}
+
+int
+ibcs2_sigsys(struct proc *p, struct ibcs2_signal_args *args, int *retval)
+{
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'sigsys' signo=%d(%s) ",
+ args->signo & IBCS2_SIGMASK,
+ ibcs2_sig_to_str(args->signo & IBCS2_SIGMASK));
+
+ switch (args->signo & ~IBCS2_SIGMASK ) {
+ case 0x0000:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("signal() func=%x\n", args->func);
+ return ibcs2_signal(p, args, retval);
+ case 0x0100:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("sigset() func=%x\n", args->func);
+ return ibcs2_sigset(p, args, retval);
+ case 0x0200:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("sighold()\n");
+ return ibcs2_sighold(p, args, retval);
+ case 0x0400:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("sigrelse()\n");
+ return ibcs2_sigrelse(p, args, retval);
+ case 0x0800:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("sigignore()\n");
+ return ibcs2_sigignore(p, args, retval);
+ case 0x1000:
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("sigpause()\n");
+ return ibcs2_sigpause(p, args, retval);
+ default:
+ printf("IBCS2: unknown signal action\n"); break;
+ }
+ *retval = -1;
+ return EINVAL;
+}
+
+struct ibcs2_sigaction_args {
+ int signo;
+ struct sigaction *osa, *nsa;
+};
+
+int
+ibcs2_sigaction(struct proc *p, struct ibcs2_sigaction_args *args, int *retval)
+{
+ struct sigaction vec;
+ register struct sigaction *sa;
+ register struct sigacts *ps = p->p_sigacts;
+ register int sig;
+ int bit, error;
+
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'sigaction' signo=%d(%s)\n",
+ args->signo, ibcs2_sig_to_str(args->signo));
+ sig = ibcs2_to_bsd_signal[LEGAL_SIG(args->signo)];
+ if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) {
+ *retval = -1;
+ return EINVAL;
+ }
+ sa = &vec;
+ if (args->osa) {
+ sa->sa_handler = ps->ps_sigact[sig];
+ sa->sa_mask = ps->ps_catchmask[sig];
+ bit = sigmask(sig);
+ sa->sa_flags = 0;
+ if (p->p_flag & SA_NOCLDSTOP)
+ sa->sa_flags = IBCS2_SA_NOCLDSTOP;
+ if (error = copyout((caddr_t)sa, (caddr_t)args->osa,
+ sizeof(vec))) {
+ *retval = -1;
+ return error;
+ }
+ }
+ if (args->nsa) {
+ if (error = copyin((caddr_t)args->nsa, (caddr_t)sa,
+ sizeof(vec))) {
+ *retval = -1;
+ return error;
+ }
+ /*
+ * iBCS2 only defines one SA_ flag right now
+ */
+ if (vec.sa_flags & IBCS2_SA_NOCLDSTOP)
+ vec.sa_flags = SA_NOCLDSTOP;
+ setsigvec(p, sig, sa);
+ }
+ *retval = 0;
+ return 0;
+}
+
+struct ibcs2_sigprocmask_args {
+ int how;
+ unsigned long *mask;
+ unsigned long *omask;
+};
+
+int
+ibcs2_sigprocmask(struct proc *p, struct ibcs2_sigprocmask_args *args, int *retval)
+{
+ int error;
+ sigset_t umask;
+ sigset_t omask = bsd_to_ibcs2_sigmask(p->p_sigmask);
+
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'sigprocmask' how=%d\n", args->how);
+ if (error = copyin(args->mask, &umask, sizeof(args->mask))) {
+ *retval = -1;
+ return error;
+ }
+ umask = ibcs2_to_bsd_sigmask(umask);
+ if (args->omask)
+ if (error = copyout(&omask, args->omask, sizeof(args->omask))) {
+ *retval = -1;
+ return error;
+ }
+ (void) splhigh();
+ switch (args->how) {
+ case 0: /* SIG_SETMASK */
+ p->p_sigmask = umask &~ DONTMASK;
+ break;
+
+ case 1: /* SIG_BLOCK */
+ p->p_sigmask |= (umask &~ DONTMASK);
+ break;
+
+ case 2: /* SIG_UNBLOCK */
+ p->p_sigmask &= ~umask;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ (void) spl0();
+ if (error)
+ *retval = -1;
+ else
+ *retval = 0;
+ return error;
+}
+
+struct ibcs2_sigpending_args {
+ unsigned long *sigs;
+};
+
+int
+ibcs2_sigpending(struct proc *p, struct ibcs2_sigpending_args *args, int *retval)
+{
+ int error;
+ sigset_t mask = bsd_to_ibcs2_sigmask(p->p_siglist);
+
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'sigpending' which=%x\n", args->sigs);
+ if (error = copyout(&mask, args->sigs, sizeof(unsigned long)))
+ *retval = -1;
+ else
+ *retval = 0;
+ return error;
+}
+
+struct ibcs2_sigsuspend_args {
+ sigset_t *mask;
+};
+
+int
+ibcs2_sigsuspend(struct proc *p, struct ibcs2_sigsuspend_args *args, int *retval)
+{
+ sigset_t mask = ibcs2_to_bsd_sigmask((sigset_t)args->mask);
+
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'sigsuspend'\n");
+ return sigsuspend(p, &mask, retval);
+}
+
+struct kill_args {
+ int pid;
+ int signo;
+};
+
+int
+ibcs2_kill(struct proc *p, struct kill_args *args, int *retval)
+{
+ struct kill_args tmp;
+
+ if (ibcs2_trace & IBCS2_TRACE_SIGNAL)
+ printf("IBCS2: 'kill' pid=%d, sig=%d(%s)\n", args->pid,
+ args->signo, ibcs2_sig_to_str(args->signo));
+ tmp.pid = args->pid;
+ tmp.signo = (args->signo < IBCS2_NSIG) ?
+ ibcs2_to_bsd_signal[args->signo] : IBCS2_NSIG;
+ return kill(p, &tmp, retval);
+}
+
OpenPOWER on IntegriCloud