/* Copyright 1990,1991,1992,1994 Eric R. Smith. All rights reserved. */ /* dossig.c:: dos signal handling routines */ #include "mint.h" void ARGS_ON_STACK sig_user P_((int vec)); /* * send a signal to another process. If pid > 0, send the signal just to * that process. If pid < 0, send the signal to all processes whose process * group is -pid. If pid == 0, send the signal to all processes with the * same process group id. * * note: post_sig just posts the signal to the process. */ long ARGS_ON_STACK p_kill(pid, sig) int pid, sig; { PROC *p; long r; TRACE(("Pkill(%d, %d)", pid, sig)); if (sig < 0 || sig >= NSIG) { DEBUG(("Pkill: signal out of range")); return ERANGE; } if (pid < 0) r = killgroup(-pid, sig, 0); else if (pid == 0) r = killgroup(curproc->pgrp, sig, 0); else { p = pid2proc(pid); if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) { DEBUG(("Pkill: pid %d not found", pid)); return EFILNF; } if (curproc->euid && curproc->ruid != p->ruid) { DEBUG(("Pkill: wrong user")); return EACCDN; } /* if the user sends signal 0, don't deliver it -- for users, signal * 0 is a null signal used to test the existence of a process */ if (sig != 0) post_sig(p, sig); r = 0; } if (r == 0) { check_sigs(); TRACE(("Pkill: returning OK")); } return r; } /* * set a user-specified signal handler, POSIX.1 style * "oact", if non-null, gets the old signal handling * behaviour; "act", if non-null, specifies new * behaviour */ long ARGS_ON_STACK p_sigaction(sig, act, oact) int sig; const struct sigaction *act; struct sigaction *oact; { TRACE(("Psigaction(%d)", sig)); if (sig < 1 || sig >= NSIG) return ERANGE; if (act && (sig == SIGKILL || sig == SIGSTOP)) return EACCDN; if (oact) { oact->sa_handler = curproc->sighandle[sig]; oact->sa_mask = curproc->sigextra[sig]; oact->sa_flags = curproc->sigflags[sig] & SAUSER; } if (act) { ushort flags; curproc->sighandle[sig] = act->sa_handler; curproc->sigextra[sig] = act->sa_mask & ~UNMASKABLE; /* only the flags in SAUSER can be changed by the user */ flags = curproc->sigflags[sig] & ~SAUSER; flags |= act->sa_flags & SAUSER; curproc->sigflags[sig] = flags; /* various special things that should happen */ if (act->sa_handler == SIG_IGN) { /* discard pending signals */ curproc->sigpending &= ~(1L<sigmask &= ~(1L<= NSIG) return ERANGE; if (sig == SIGKILL || sig == SIGSTOP) return EACCDN; oldhandle = curproc->sighandle[sig]; curproc->sighandle[sig] = handler; curproc->sigextra[sig] = 0; curproc->sigflags[sig] = 0; /* various special things that should happen */ if (handler == SIG_IGN) { /* discard pending signals */ curproc->sigpending &= ~(1L<sigmask &= ~(1L<sigmask; curproc->sigmask |= mask; return oldmask; } /* * set the signals that we're blocking. Some signals (e.g. SIGKILL) * can't be masked. * Returns the old mask. */ long ARGS_ON_STACK p_sigsetmask(mask) ulong mask; { ulong oldmask; TRACE(("Psigsetmask(%lx)",mask)); oldmask = curproc->sigmask; curproc->sigmask = mask & ~(UNMASKABLE); check_sigs(); /* maybe we unmasked something */ return oldmask; } /* * p_sigpending: return which signals are pending delivery */ long ARGS_ON_STACK p_sigpending() { TRACE(("Psigpending()")); check_sigs(); /* clear out any that are going to be delivered soon */ /* note that signal #0 is used internally, so we don't tell the process * about it */ return curproc->sigpending & ~1L; } /* * p_sigpause: atomically set the signals that we're blocking, then pause. * Some signals (e.g. SIGKILL) can't be masked. */ long ARGS_ON_STACK p_sigpause(mask) ulong mask; { ulong oldmask; TRACE(("Psigpause(%lx)", mask)); oldmask = curproc->sigmask; curproc->sigmask = mask & ~(UNMASKABLE); if (curproc->sigpending & ~(curproc->sigmask)) check_sigs(); /* a signal is immediately pending */ else sleep(IO_Q, -1L); curproc->sigmask = oldmask; check_sigs(); /* maybe we unmasked something */ TRACE(("Psigpause: returning OK")); return 0; } /* * p_sigintr: Set an exception vector to send us the specified signal. */ typedef struct usig { int vec; /* exception vector number */ int sig; /* signal to send */ PROC *proc; /* process to get signal */ long oldv; /* old exception vector value */ struct usig *next; /* next entry ... */ } usig; static usig *usiglst; extern long mcpu; long ARGS_ON_STACK p_sigintr(vec, sig) int vec; int sig; { extern void new_intr(); /* in intr.spp */ long vec2; usig *new; if (!sig) /* ignore signal 0 */ return 0; vec2 = (long) new_intr; #ifndef ONLY030 if (mcpu == 0) /* put vector number in high byte of vector address */ vec2 |= ((long) vec) << 24; #endif new = kmalloc(sizeof(usig)); if (!new) /* hope this never happens...! */ return ENSMEM; new->vec = vec; new->sig = sig; new->proc = curproc; new->next = usiglst; /* simple unsorted list... */ usiglst = new; new->oldv = setexc(vec, vec2); return new->oldv; } /* * Find the process that requested this interrupt, and send it a signal. * Called at interrupt time by new_intr() from intr.spp, with interrupt * vector number on the stack. */ void ARGS_ON_STACK sig_user(vec) int vec; { usig *ptr; for (ptr = usiglst; ptr; ptr=ptr->next) if (vec == ptr->vec) { if (ptr->proc->wait_q != ZOMBIE_Q && ptr->proc->wait_q != TSR_Q) { post_sig(ptr->proc, ptr->sig); } #if 0 /* Search entire list, to allow multiple processes to respond to the same interrupt. (Why/when would you want that?) */ break; #endif } /* * Clear in-service bit for ST MFP interrupts */ if (vec >= 64 && vec < 80) { char *mfp, c; if (vec < 72) /* Register B */ mfp = (char *)0xfffffa11L; else /* Register A */ mfp = (char *)0xfffffa0fL; c = 1 << (vec & 7); *mfp = ~c; } } /* * cancelsigintrs: remove any interrupts requested by this process, called * at process termination. */ void cancelsigintrs() { usig *ptr, **old, *nxt; short s = spl7(); for (old=&usiglst, ptr=usiglst; ptr; ) { nxt = ptr->next; if (ptr->proc == curproc) { setexc(ptr->vec, ptr->oldv); *old = nxt; kfree(ptr); } else { old = &(ptr->next); } ptr = nxt; } spl(s); }