return flags and generation number in stat structure
[unix-history] / usr / src / sys / kern / kern_sig.c
index 99800df..9c09e71 100644 (file)
@@ -1,31 +1,51 @@
-/*     kern_sig.c      6.1     83/08/20        */
-
-#include "../machine/reg.h"
-#include "../machine/pte.h"
-#include "../machine/psl.h"
-
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/inode.h"
-#include "../h/proc.h"
-#include "../h/timeb.h"
-#include "../h/times.h"
-#include "../h/conf.h"
-#include "../h/buf.h"
-#include "../h/mount.h"
-#include "../h/text.h"
-#include "../h/seg.h"
-#include "../h/vm.h"
-#include "../h/acct.h"
-#include "../h/uio.h"
-#include "../h/kernel.h"
-#include "../h/nami.h"
-
-#define        mask(s) (1 << ((s)-1))
-#define        cantmask        (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP))
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)kern_sig.c  7.8 (Berkeley) %G%
+ */
 
 
+#include "param.h"
+#include "systm.h"
+#include "user.h"
+#include "vnode.h"
+#include "proc.h"
+#include "timeb.h"
+#include "times.h"
+#include "buf.h"
+#include "mount.h"
+#include "text.h"
+#include "seg.h"
+#include "vm.h"
+#include "acct.h"
+#include "uio.h"
+#include "file.h"
+#include "kernel.h"
+
+#include "machine/reg.h"
+#include "machine/pte.h"
+#include "machine/psl.h"
+#include "machine/mtpr.h"
+
+#define        cantmask        (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP))
+#define        stopsigmask     (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \
+                       sigmask(SIGTTIN)|sigmask(SIGTTOU))
+
+/*
+ * Generalized interface signal handler.
+ */
 sigvec()
 {
        register struct a {
 sigvec()
 {
        register struct a {
@@ -36,6 +56,7 @@ sigvec()
        struct sigvec vec;
        register struct sigvec *sv;
        register int sig;
        struct sigvec vec;
        register struct sigvec *sv;
        register int sig;
+       int bit;
 
        sig = uap->signo;
        if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) {
 
        sig = uap->signo;
        if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) {
@@ -46,7 +67,12 @@ sigvec()
        if (uap->osv) {
                sv->sv_handler = u.u_signal[sig];
                sv->sv_mask = u.u_sigmask[sig];
        if (uap->osv) {
                sv->sv_handler = u.u_signal[sig];
                sv->sv_mask = u.u_sigmask[sig];
-               sv->sv_onstack = (u.u_sigonstack & mask(sig)) != 0;
+               bit = sigmask(sig);
+               sv->sv_flags = 0;
+               if ((u.u_sigonstack & bit) != 0)
+                       sv->sv_flags |= SV_ONSTACK;
+               if ((u.u_sigintr & bit) != 0)
+                       sv->sv_flags |= SV_INTERRUPT;
                u.u_error =
                    copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec));
                if (u.u_error)
                u.u_error =
                    copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec));
                if (u.u_error)
@@ -72,15 +98,19 @@ setsigvec(sig, sv)
        register struct proc *p;
        register int bit;
 
        register struct proc *p;
        register int bit;
 
-       bit = mask(sig);
+       bit = sigmask(sig);
        p = u.u_procp;
        /*
         * Change setting atomically.
         */
        p = u.u_procp;
        /*
         * Change setting atomically.
         */
-       (void) spl6();
+       (void) splhigh();
        u.u_signal[sig] = sv->sv_handler;
        u.u_sigmask[sig] = sv->sv_mask &~ cantmask;
        u.u_signal[sig] = sv->sv_handler;
        u.u_sigmask[sig] = sv->sv_mask &~ cantmask;
-       if (sv->sv_onstack)
+       if (sv->sv_flags & SV_INTERRUPT)
+               u.u_sigintr |= bit;
+       else
+               u.u_sigintr &= ~bit;
+       if (sv->sv_flags & SV_ONSTACK)
                u.u_sigonstack |= bit;
        else
                u.u_sigonstack &= ~bit;
                u.u_sigonstack |= bit;
        else
                u.u_sigonstack &= ~bit;
@@ -101,33 +131,33 @@ setsigvec(sig, sv)
 sigblock()
 {
        struct a {
 sigblock()
 {
        struct a {
-               int     sigmask;
+               int     mask;
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
-       (void) spl6();
+       (void) splhigh();
        u.u_r.r_val1 = p->p_sigmask;
        u.u_r.r_val1 = p->p_sigmask;
-       p->p_sigmask |= uap->sigmask &~ cantmask;
+       p->p_sigmask |= uap->mask &~ cantmask;
        (void) spl0();
 }
 
 sigsetmask()
 {
        struct a {
        (void) spl0();
 }
 
 sigsetmask()
 {
        struct a {
-               int     sigmask;
+               int     mask;
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
-       (void) spl6();
+       (void) splhigh();
        u.u_r.r_val1 = p->p_sigmask;
        u.u_r.r_val1 = p->p_sigmask;
-       p->p_sigmask = uap->sigmask &~ cantmask;
+       p->p_sigmask = uap->mask &~ cantmask;
        (void) spl0();
 }
 
 sigpause()
 {
        struct a {
        (void) spl0();
 }
 
 sigpause()
 {
        struct a {
-               int     sigmask;
+               int     mask;
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
        } *uap = (struct a *)u.u_ap;
        register struct proc *p = u.u_procp;
 
@@ -140,13 +170,12 @@ sigpause()
         */
        u.u_oldmask = p->p_sigmask;
        p->p_flag |= SOMASK;
         */
        u.u_oldmask = p->p_sigmask;
        p->p_flag |= SOMASK;
-       p->p_sigmask = uap->sigmask &~ cantmask;
+       p->p_sigmask = uap->mask &~ cantmask;
        for (;;)
                sleep((caddr_t)&u, PSLEP);
        /*NOTREACHED*/
 }
 #undef cantmask
        for (;;)
                sleep((caddr_t)&u, PSLEP);
        /*NOTREACHED*/
 }
 #undef cantmask
-#undef mask
 
 sigstack()
 {
 
 sigstack()
 {
@@ -170,92 +199,139 @@ sigstack()
        }
 }
 
        }
 }
 
-/* KILL SHOULD BE UPDATED */
-
 kill()
 {
        register struct a {
                int     pid;
                int     signo;
        } *uap = (struct a *)u.u_ap;
 kill()
 {
        register struct a {
                int     pid;
                int     signo;
        } *uap = (struct a *)u.u_ap;
+       register struct proc *p;
 
 
-       u.u_error = kill1(uap->signo < 0,
-               uap->signo < 0 ? -uap->signo : uap->signo, uap->pid);
+       if (uap->signo < 0 || uap->signo > NSIG) {
+               u.u_error = EINVAL;
+               return;
+       }
+       if (uap->pid > 0) {
+               /* kill single process */
+               p = pfind(uap->pid);
+               if (p == 0) {
+                       u.u_error = ESRCH;
+                       return;
+               }
+               if (u.u_uid && u.u_uid != p->p_uid)
+                       u.u_error = EPERM;
+               else if (uap->signo)
+                       psignal(p, uap->signo);
+               return;
+       }
+       switch (uap->pid) {
+       case -1:                /* broadcast signal */
+               u.u_error = killpg1(uap->signo, 0, 1);
+               break;
+       case 0:                 /* signal own process group */
+               u.u_error = killpg1(uap->signo, 0, 0);
+               break;
+       default:                /* negative explicit process group */
+               u.u_error = killpg1(uap->signo, -uap->pid, 0);
+               break;
+       }
+       return;
 }
 
 killpg()
 {
        register struct a {
 }
 
 killpg()
 {
        register struct a {
-               int     pgrp;
+               int     pgid;
                int     signo;
        } *uap = (struct a *)u.u_ap;
 
                int     signo;
        } *uap = (struct a *)u.u_ap;
 
-       u.u_error = kill1(1, uap->signo, uap->pgrp);
+       if (uap->signo < 0 || uap->signo > NSIG) {
+               u.u_error = EINVAL;
+               return;
+       }
+       u.u_error = killpg1(uap->signo, uap->pgid, 0);
 }
 
 /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
 
 }
 
 /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */
 
-kill1(ispgrp, signo, who)
-       int ispgrp, signo, who;
+killpg1(signo, pgid, all)
+       int signo, pgid, all;
 {
        register struct proc *p;
 {
        register struct proc *p;
-       int f, priv = 0;
-
-       if (signo < 0 || signo > NSIG)
-               return (EINVAL);
-       if (who > 0 && !ispgrp) {
-               p = pfind(who);
-               if (p == 0 || u.u_uid && u.u_uid != p->p_uid)
-                       return (ESRCH);
-               if (signo)
-                       psignal(p, signo);
-               return (0);
-       }
-       if (who == -1 && u.u_uid == 0)
-               priv++, who = 0, ispgrp = 1;    /* like sending to pgrp */
-       else if (who == 0) {
-               /*
-                * Zero process id means send to my process group.
+       struct pgrp *pgrp;
+       int f = 0, error = 0;
+
+       
+       if (all)        
+               /* 
+                * broadcast 
                 */
                 */
-               ispgrp = 1;
-               who = u.u_procp->p_pgrp;
-               if (who == 0)
-                       return (EINVAL);
-       }
-       for (f = 0, p = proc; p < procNPROC; p++) {
-               if (p->p_stat == NULL)
-                       continue;
-               if (!ispgrp) {
-                       if (p->p_pid != who)
+               for (p = allproc; p != NULL; p = p->p_nxt) {
+                       if (p->p_ppid == 0 || p->p_flag&SSYS || 
+                           p == u.u_procp ||
+                          (u.u_uid && u.u_uid != p->p_uid && 
+                          !(signo == SIGCONT && inferior(p))))
                                continue;
                                continue;
-               } else if (p->p_pgrp != who && priv == 0 || p->p_ppid == 0 ||
-                   (p->p_flag&SSYS) || (priv && p == u.u_procp))
-                       continue;
-               if (u.u_uid != 0 && u.u_uid != p->p_uid &&
-                   (signo != SIGCONT || !inferior(p)))
-                       continue;
-               f++;
-               if (signo)
-                       psignal(p, signo);
+                       f++;
+                       if (signo)
+                               psignal(p, signo);
+               }
+       else {
+               if (pgid == 0)          
+                       /* 
+                        * zero pgid means send to my process group.
+                        */
+                       pgrp = u.u_procp->p_pgrp;
+               else {
+                       pgrp = pgfind(pgid);
+                       if (pgrp == NULL)
+                               return(ESRCH);
+               }
+               if (!(pgrp->pg_jobc) && 
+                    (signo==SIGTTIN || signo==SIGTTOU || signo==SIGTSTP))
+                       return(EPERM);
+               for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) {
+                       if (p->p_ppid == 0 || p->p_flag&SSYS)
+                               continue;
+                       if (u.u_uid && u.u_uid != p->p_uid && 
+                          !(signo == SIGCONT && inferior(p))) {
+                               error = EPERM;
+                               continue;
+                       }
+                       f++;
+                       if (signo)
+                               psignal(p, signo);
+               }
        }
        }
-       return (f == 0 ? ESRCH : 0);
+       return (error ? error : (f == 0 ? ESRCH : 0));
 }
 
 /*
  * Send the specified signal to
 }
 
 /*
  * Send the specified signal to
- * all processes with 'pgrp' as
+ * all processes with 'pgid' as
  * process group.
  */
  * process group.
  */
-gsignal(pgrp, sig)
-       register int pgrp;
+gsignal(pgid, sig)
+{
+       register struct pgrp *pgrp;
+
+       if (!pgid)
+               return;
+       if ((pgrp = pgfind(pgid)) == NULL)
+               return;
+       pgsignal(pgrp, sig);
+}
+
+pgsignal(pgrp, sig)
+       register struct pgrp *pgrp;
 {
        register struct proc *p;
 
 {
        register struct proc *p;
 
-       if (pgrp == 0)
+       if (!(pgrp->pg_jobc) && 
+            (sig==SIGTTIN || sig==SIGTTOU || sig==SIGTSTP))
                return;
                return;
-       for(p = proc; p < procNPROC; p++)
-               if (p->p_pgrp == pgrp)
-                       psignal(p, sig);
+       for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt)
+               psignal(p, sig);
 }
 
 /*
 }
 
 /*
@@ -268,11 +344,11 @@ psignal(p, sig)
 {
        register int s;
        register int (*action)();
 {
        register int s;
        register int (*action)();
-       int sigmask;
+       int mask;
 
        if ((unsigned)sig >= NSIG)
                return;
 
        if ((unsigned)sig >= NSIG)
                return;
-       sigmask = 1 << (sig-1);
+       mask = sigmask(sig);
 
        /*
         * If proc is traced, always give parent a chance.
 
        /*
         * If proc is traced, always give parent a chance.
@@ -284,19 +360,16 @@ psignal(p, sig)
                 * If the signal is being ignored,
                 * then we forget about it immediately.
                 */
                 * If the signal is being ignored,
                 * then we forget about it immediately.
                 */
-               if (p->p_sigignore & sigmask)
+               if (p->p_sigignore & mask)
                        return;
                        return;
-               if (p->p_sigmask & sigmask)
+               if (p->p_sigmask & mask)
                        action = SIG_HOLD;
                        action = SIG_HOLD;
-               else if (p->p_sigcatch & sigmask)
+               else if (p->p_sigcatch & mask)
                        action = SIG_CATCH;
                else
                        action = SIG_DFL;
        }
                        action = SIG_CATCH;
                else
                        action = SIG_DFL;
        }
-#define mask(sig)      (1<<(sig-1))
-#define        stops   (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU))
        if (sig) {
        if (sig) {
-               p->p_sig |= sigmask;
                switch (sig) {
 
                case SIGTERM:
                switch (sig) {
 
                case SIGTERM:
@@ -310,25 +383,25 @@ psignal(p, sig)
                        break;
 
                case SIGCONT:
                        break;
 
                case SIGCONT:
-                       p->p_sig &= ~stops;
+                       p->p_sig &= ~stopsigmask;
                        break;
 
                        break;
 
-               case SIGSTOP:
                case SIGTSTP:
                case SIGTTIN:
                case SIGTTOU:
                case SIGTSTP:
                case SIGTTIN:
                case SIGTTOU:
-                       p->p_sig &= ~mask(SIGCONT);
+                       /*FALLTHROUGH*/
+               case SIGSTOP:
+                       p->p_sig &= ~sigmask(SIGCONT);
                        break;
                }
                        break;
                }
+               p->p_sig |= mask;
        }
        }
-#undef mask
-#undef stops
        /*
         * Defer further processing for signals which are held.
         */
        if (action == SIG_HOLD)
                return;
        /*
         * Defer further processing for signals which are held.
         */
        if (action == SIG_HOLD)
                return;
-       s = spl6();
+       s = splhigh();
        switch (p->p_stat) {
 
        case SSLEEP:
        switch (p->p_stat) {
 
        case SSLEEP:
@@ -359,30 +432,22 @@ psignal(p, sig)
                         */
                        if (action != SIG_DFL)
                                goto run;
                         */
                        if (action != SIG_DFL)
                                goto run;
-                       /*
-                        * Don't clog system with children of init
-                        * stopped from the keyboard.
-                        */
-                       if (sig != SIGSTOP && p->p_pptr == &proc[1]) {
-                               psignal(p, SIGKILL);
-                               p->p_sig &= ~sigmask;
-                               splx(s);
-                               return;
-                       }
                        /*
                         * If a child in vfork(), stopping could
                         * cause deadlock.
                         */
                        if (p->p_flag&SVFORK)
                                goto out;
                        /*
                         * If a child in vfork(), stopping could
                         * cause deadlock.
                         */
                        if (p->p_flag&SVFORK)
                                goto out;
-                       p->p_sig &= ~sigmask;
+                       p->p_sig &= ~mask;
                        p->p_cursig = sig;
                        p->p_cursig = sig;
+                       psignal(p->p_pptr, SIGCHLD);
                        stop(p);
                        goto out;
 
                case SIGIO:
                case SIGURG:
                case SIGCHLD:
                        stop(p);
                        goto out;
 
                case SIGIO:
                case SIGURG:
                case SIGCHLD:
+               case SIGWINCH:
                        /*
                         * These signals are special in that they
                         * don't get propogated... if the process
                        /*
                         * These signals are special in that they
                         * don't get propogated... if the process
@@ -390,7 +455,7 @@ psignal(p, sig)
                         */
                        if (action != SIG_DFL)
                                goto run;
                         */
                        if (action != SIG_DFL)
                                goto run;
-                       p->p_sig &= ~sigmask;           /* take it away */
+                       p->p_sig &= ~mask;              /* take it away */
                        goto out;
 
                default:
                        goto out;
 
                default:
@@ -436,7 +501,7 @@ psignal(p, sig)
                         * Already stopped, don't need to stop again.
                         * (If we did the shell could get confused.)
                         */
                         * Already stopped, don't need to stop again.
                         * (If we did the shell could get confused.)
                         */
-                       p->p_sig &= ~sigmask;           /* take it away */
+                       p->p_sig &= ~mask;              /* take it away */
                        goto out;
 
                default:
                        goto out;
 
                default:
@@ -460,7 +525,6 @@ psignal(p, sig)
                 * It will either never be noticed, or noticed very soon.
                 */
                if (p == u.u_procp && !noproc)
                 * It will either never be noticed, or noticed very soon.
                 */
                if (p == u.u_procp && !noproc)
-#include "../vax/mtpr.h"
                        aston();
                goto out;
        }
                        aston();
                goto out;
        }
@@ -470,13 +534,7 @@ run:
         * Raise priority to at least PUSER.
         */
        if (p->p_pri > PUSER)
         * Raise priority to at least PUSER.
         */
        if (p->p_pri > PUSER)
-               if ((p != u.u_procp || noproc) && p->p_stat == SRUN &&
-                   (p->p_flag & SLOAD)) {
-                       remrq(p);
-                       p->p_pri = PUSER;
-                       setrq(p);
-               } else
-                       p->p_pri = PUSER;
+               p->p_pri = PUSER;
        setrun(p);
 out:
        splx(s);
        setrun(p);
 out:
        splx(s);
@@ -498,7 +556,7 @@ issig()
 {
        register struct proc *p;
        register int sig;
 {
        register struct proc *p;
        register int sig;
-       int sigbits, sigmask;
+       int sigbits, mask;
 
        p = u.u_procp;
        for (;;) {
 
        p = u.u_procp;
        for (;;) {
@@ -506,19 +564,19 @@ issig()
                if ((p->p_flag&STRC) == 0)
                        sigbits &= ~p->p_sigignore;
                if (p->p_flag&SVFORK)
                if ((p->p_flag&STRC) == 0)
                        sigbits &= ~p->p_sigignore;
                if (p->p_flag&SVFORK)
-#define bit(a) (1<<(a-1))
-                       sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU));
+                       sigbits &= ~stopsigmask;
                if (sigbits == 0)
                        break;
                if (sigbits == 0)
                        break;
-               sig = ffs(sigbits);
-               sigmask = 1 << (sig-1);
-               p->p_sig &= ~sigmask;           /* take the signal! */
+               sig = ffs((long)sigbits);
+               mask = sigmask(sig);
+               p->p_sig &= ~mask;              /* take the signal! */
                p->p_cursig = sig;
                if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) {
                        /*
                         * If traced, always stop, and stay
                         * stopped until released by the parent.
                         */
                p->p_cursig = sig;
                if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) {
                        /*
                         * If traced, always stop, and stay
                         * stopped until released by the parent.
                         */
+                       psignal(p->p_pptr, SIGCHLD);
                        do {
                                stop(p);
                                swtch();
                        do {
                                stop(p);
                                swtch();
@@ -531,7 +589,7 @@ issig()
                         * This ensures that p_sig* and u_signal are consistent.
                         */
                        if ((p->p_flag&STRC) == 0) {
                         * This ensures that p_sig* and u_signal are consistent.
                         */
                        if ((p->p_flag&STRC) == 0) {
-                               p->p_sig |= sigmask;
+                               p->p_sig |= mask;
                                continue;
                        }
 
                                continue;
                        }
 
@@ -548,13 +606,13 @@ issig()
                         * If signal is being masked put it back
                         * into p_sig and look for other signals.
                         */
                         * If signal is being masked put it back
                         * into p_sig and look for other signals.
                         */
-                       sigmask = 1 << (sig-1);
-                       if (p->p_sigmask & sigmask) {
-                               p->p_sig |= sigmask;
+                       mask = sigmask(sig);
+                       if (p->p_sigmask & mask) {
+                               p->p_sig |= mask;
                                continue;
                        }
                }
                                continue;
                        }
                }
-               switch (u.u_signal[sig]) {
+               switch ((int)u.u_signal[sig]) {
 
                case SIG_DFL:
                        /*
 
                case SIG_DFL:
                        /*
@@ -567,19 +625,10 @@ issig()
                        case SIGTSTP:
                        case SIGTTIN:
                        case SIGTTOU:
                        case SIGTSTP:
                        case SIGTTIN:
                        case SIGTTOU:
-                               /*
-                                * Children of init aren't allowed to stop
-                                * on signals from the keyboard.
-                                */
-                               if (p->p_pptr == &proc[1]) {
-                                       psignal(p, SIGKILL);
-                                       continue;
-                               }
-                               /* fall into ... */
-
                        case SIGSTOP:
                                if (p->p_flag&STRC)
                                        continue;
                        case SIGSTOP:
                                if (p->p_flag&STRC)
                                        continue;
+                               psignal(p->p_pptr, SIGCHLD);
                                stop(p);
                                swtch();
                                continue;
                                stop(p);
                                swtch();
                                continue;
@@ -588,6 +637,7 @@ issig()
                        case SIGCHLD:
                        case SIGURG:
                        case SIGIO:
                        case SIGCHLD:
                        case SIGURG:
                        case SIGIO:
+                       case SIGWINCH:
                                /*
                                 * These signals are normally not
                                 * sent if the action is the default.
                                /*
                                 * These signals are normally not
                                 * sent if the action is the default.
@@ -634,7 +684,8 @@ send:
 
 /*
  * Put the argument process into the stopped
 
 /*
  * Put the argument process into the stopped
- * state and notify the parent via wakeup and/or signal.
+ * state and notify the parent via wakeup.
+ * Signals are handled elsewhere.
  */
 stop(p)
        register struct proc *p;
  */
 stop(p)
        register struct proc *p;
@@ -643,12 +694,6 @@ stop(p)
        p->p_stat = SSTOP;
        p->p_flag &= ~SWTED;
        wakeup((caddr_t)p->p_pptr);
        p->p_stat = SSTOP;
        p->p_flag &= ~SWTED;
        wakeup((caddr_t)p->p_pptr);
-       /*
-        * Avoid sending signal to parent if process is traced
-        */
-       if (p->p_flag&STRC)
-               return;
-       psignal(p->p_pptr, SIGCHLD);
 }
 
 /*
 }
 
 /*
@@ -664,14 +709,14 @@ psig()
 {
        register struct proc *p = u.u_procp;
        register int sig = p->p_cursig;
 {
        register struct proc *p = u.u_procp;
        register int sig = p->p_cursig;
-       int sigmask = 1 << (sig - 1), returnmask;
+       int mask = sigmask(sig), returnmask;
        register int (*action)();
 
        if (sig == 0)
                panic("psig");
        action = u.u_signal[sig];
        if (action != SIG_DFL) {
        register int (*action)();
 
        if (sig == 0)
                panic("psig");
        action = u.u_signal[sig];
        if (action != SIG_DFL) {
-               if (action == SIG_IGN || (p->p_sigmask & sigmask))
+               if (action == SIG_IGN || (p->p_sigmask & mask))
                        panic("psig action");
                u.u_error = 0;
                /*
                        panic("psig action");
                u.u_error = 0;
                /*
@@ -684,20 +729,20 @@ psig()
                 * mask from before the sigpause is what we want restored
                 * after the signal processing is completed.
                 */
                 * mask from before the sigpause is what we want restored
                 * after the signal processing is completed.
                 */
-               (void) spl6();
+               (void) splhigh();
                if (p->p_flag & SOUSIG) {
                        if (sig != SIGILL && sig != SIGTRAP) {
                                u.u_signal[sig] = SIG_DFL;
                if (p->p_flag & SOUSIG) {
                        if (sig != SIGILL && sig != SIGTRAP) {
                                u.u_signal[sig] = SIG_DFL;
-                               p->p_sigcatch &= ~sigmask;
+                               p->p_sigcatch &= ~mask;
                        }
                        }
-                       sigmask = 0;
+                       mask = 0;
                }
                if (p->p_flag & SOMASK) {
                        returnmask = u.u_oldmask;
                        p->p_flag &= ~SOMASK;
                } else
                        returnmask = p->p_sigmask;
                }
                if (p->p_flag & SOMASK) {
                        returnmask = u.u_oldmask;
                        p->p_flag &= ~SOMASK;
                } else
                        returnmask = p->p_sigmask;
-               p->p_sigmask |= u.u_sigmask[sig] | sigmask;
+               p->p_sigmask |= u.u_sigmask[sig] | mask;
                (void) spl0();
                u.u_ru.ru_nsignals++;
                sendsig(action, sig, returnmask);
                (void) spl0();
                u.u_ru.ru_nsignals++;
                sendsig(action, sig, returnmask);
@@ -717,7 +762,7 @@ psig()
        case SIGSEGV:
        case SIGSYS:
                u.u_arg[0] = sig;
        case SIGSEGV:
        case SIGSYS:
                u.u_arg[0] = sig;
-               if (core())
+               if (core() == 0)
                        sig += 0200;
        }
        exit(sig);
                        sig += 0200;
        }
        exit(sig);
@@ -735,47 +780,61 @@ psig()
  */
 core()
 {
  */
 core()
 {
-       register struct inode *ip;
-       extern schar();
+       register struct vnode *vp;
+       register struct nameidata *ndp = &u.u_nd;
+       struct vattr vattr;
+       int error;
 
        if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid)
 
        if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid)
-               return (0);
-       if (ctob(UPAGES+u.u_dsize+u.u_ssize) >=
+               return (EFAULT);
+       if (ctob(UPAGES + u.u_dsize + u.u_ssize) >=
            u.u_rlimit[RLIMIT_CORE].rlim_cur)
            u.u_rlimit[RLIMIT_CORE].rlim_cur)
-               return (0);
-       u.u_error = 0;
-       u.u_dirp = "core";
-       ip = namei(schar, CREATE, 1);
-       if (ip == NULL) {
-               if (u.u_error)
-                       return (0);
-               ip = maknode(0644);
-               if (ip==NULL)
-                       return (0);
+               return (EFAULT);
+       if (u.u_procp->p_textp) {
+               VOP_LOCK(u.u_procp->p_textp->x_vptr);
+               error = vn_access(u.u_procp->p_textp->x_vptr, VREAD, u.u_cred);
+               VOP_UNLOCK(u.u_procp->p_textp->x_vptr);
+               if (error)
+                       return (EFAULT);
        }
        }
-       if (access(ip, IWRITE) ||
-          (ip->i_mode&IFMT) != IFREG ||
-          ip->i_nlink != 1) {
-               u.u_error = EFAULT;
+       ndp->ni_segflg = UIO_SYSSPACE;
+       ndp->ni_dirp = "core";
+       if (error = vn_open(ndp, FCREAT|FWRITE, 0644))
+               return (error);
+       vp = ndp->ni_vp;
+       if (vp->v_type != VREG ||
+           VOP_GETATTR(vp, &vattr, u.u_cred) ||
+           vattr.va_nlink != 1) {
+               error = EFAULT;
                goto out;
        }
                goto out;
        }
-       itrunc(ip, (u_long)0);
+#ifdef MMAP
+       { register int fd;
+       /* unmasp funky devices in the user's address space */
+       for (fd = 0; fd < u.u_lastfile; fd++)
+               if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED))
+                       munmapfd(fd);
+       }
+#endif
+       vattr_null(&vattr);
+       vattr.va_size = 0;
+       VOP_SETATTR(vp, &vattr, u.u_cred);
        u.u_acflag |= ACORE;
        u.u_acflag |= ACORE;
-       u.u_error = rdwri(UIO_WRITE, ip,
-           (caddr_t)&u,
-           ctob(UPAGES),
-           0, 1, (int *)0);
-       if (u.u_error == 0)
-               u.u_error = rdwri(UIO_WRITE, ip,
+       error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&u, ctob(UPAGES), (off_t)0,
+           UIO_SYSSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
+       if (error == 0)
+               error = vn_rdwr(UIO_WRITE, vp,
                    (caddr_t)ctob(dptov(u.u_procp, 0)),
                    (caddr_t)ctob(dptov(u.u_procp, 0)),
-                   ctob(u.u_dsize),
-                   ctob(UPAGES), 0, (int *)0);
-       if (u.u_error == 0)
-               u.u_error = rdwri(UIO_WRITE, ip,
+                   (int)ctob(u.u_dsize), (off_t)ctob(UPAGES),
+                   UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
+       if (error == 0)
+               error = vn_rdwr(UIO_WRITE, vp,
                    (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)),
                    (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)),
-                   ctob(u.u_ssize),
-                   ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0);
+                   (int)ctob(u.u_ssize),
+                   (off_t)ctob(UPAGES) + ctob(u.u_dsize),
+                   UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0);
 out:
 out:
-       iput(ip);
-       return (u.u_error == 0);
+       if (vp)
+               vrele(vp);
+       return (error);
 }
 }