BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / kern / kern_proc.c
index 27dba8c..daea47f 100644 (file)
@@ -1,92 +1,78 @@
 /*
 /*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     @(#)kern_proc.c 7.3 (Berkeley) %G%
+ * 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.
+ * 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.
+ *
+ *     @(#)kern_proc.c 7.16 (Berkeley) 6/28/91
  */
 
  */
 
-#include "../machine/reg.h"
-#include "../machine/pte.h"
-#include "../machine/psl.h"
-
 #include "param.h"
 #include "systm.h"
 #include "map.h"
 #include "param.h"
 #include "systm.h"
 #include "map.h"
-#include "dir.h"
-#include "user.h"
 #include "kernel.h"
 #include "proc.h"
 #include "buf.h"
 #include "seg.h"
 #include "acct.h"
 #include "wait.h"
 #include "kernel.h"
 #include "proc.h"
 #include "buf.h"
 #include "seg.h"
 #include "acct.h"
 #include "wait.h"
-#include "vm.h"
-#include "text.h"
 #include "file.h"
 #include "file.h"
-#include "quota.h"
+#include "../ufs/quota.h"
 #include "uio.h"
 #include "malloc.h"
 #include "mbuf.h"
 #include "uio.h"
 #include "malloc.h"
 #include "mbuf.h"
+#include "ioctl.h"
 #include "tty.h"
 
 #include "tty.h"
 
-/*
- * Clear any pending stops for top and all descendents.
- */
-spgrp(top)
-       struct proc *top;
-{
-       register struct proc *p;
-       int f = 0;
-
-       p = top;
-       for (;;) {
-               p->p_sig &=
-                         ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
-               f++;
-               /*
-                * If this process has children, descend to them next,
-                * otherwise do any siblings, and if done with this level,
-                * follow back up the tree (but not past top).
-                */
-               if (p->p_cptr)
-                       p = p->p_cptr;
-               else if (p == top)
-                       return (f);
-               else if (p->p_osptr)
-                       p = p->p_osptr;
-               else for (;;) {
-                       p = p->p_pptr;
-                       if (p == top)
-                               return (f);
-                       if (p->p_osptr) {
-                               p = p->p_osptr;
-                               break;
-                       }
-               }
-       }
-}
-
 /*
  * Is p an inferior of the current process?
  */
 inferior(p)
        register struct proc *p;
 {
 /*
  * Is p an inferior of the current process?
  */
 inferior(p)
        register struct proc *p;
 {
-       for (; p != u.u_procp; p = p->p_pptr)
-               if (p->p_ppid == 0)
+
+       for (; p != curproc; p = p->p_pptr)
+               if (p->p_pid == 0)
                        return (0);
        return (1);
 }
 
                        return (0);
        return (1);
 }
 
+/*
+ * Locate a process by number
+ */
 struct proc *
 pfind(pid)
        register pid;
 {
 struct proc *
 pfind(pid)
        register pid;
 {
-       register struct proc *p;
+       register struct proc *p = pidhash[PIDHASH(pid)];
 
 
-       for (p = &proc[pidhash[PIDHASH(pid)]] ; 
-            p != &proc[0]; p = &proc[p->p_idhash])
+       for (; p; p = p->p_hash)
                if (p->p_pid == pid)
                        return (p);
        return ((struct proc *)0);
                if (p->p_pid == pid)
                        return (p);
        return ((struct proc *)0);
@@ -103,36 +89,41 @@ pgfind(pgid)
 
        for (; pgrp; pgrp = pgrp->pg_hforw)
                if (pgrp->pg_id == pgid)
 
        for (; pgrp; pgrp = pgrp->pg_hforw)
                if (pgrp->pg_id == pgid)
-                       return(pgrp);
+                       return (pgrp);
        return ((struct pgrp *)0);
 }
 
 /*
  * Move p to a new or existing process group (and session)
  */
        return ((struct pgrp *)0);
 }
 
 /*
  * Move p to a new or existing process group (and session)
  */
-pgmv(p, pgid, mksess)
+enterpgrp(p, pgid, mksess)
        register struct proc *p;
        pid_t pgid;
 {
        register struct pgrp *pgrp = pgfind(pgid);
        register struct proc *p;
        pid_t pgid;
 {
        register struct pgrp *pgrp = pgfind(pgid);
-       register struct proc **pp = &p->p_pgrp->pg_mem;
+       register struct proc **pp;
        register struct proc *cp;
        register struct proc *cp;
-       register n;
+       int n;
 
 
+#ifdef DIAGNOSTIC
        if (pgrp && mksess)     /* firewalls */
        if (pgrp && mksess)     /* firewalls */
-               panic("pgmv: setsid into non-empty pgrp %d\n", pgid);
+               panic("enterpgrp: setsid into non-empty pgrp");
        if (SESS_LEADER(p))
        if (SESS_LEADER(p))
-               panic("pgmv: session leader attempted setpgrp\n");
-       if (!pgrp) {
+               panic("enterpgrp: session leader attempted setpgrp");
+#endif
+       if (pgrp == NULL) {
                /*
                 * new process group
                 */
                /*
                 * new process group
                 */
+#ifdef DIAGNOSTIC
                if (p->p_pid != pgid)
                if (p->p_pid != pgid)
-                       panic("pgmv: new pgrp and pid != pgid\n");
+                       panic("enterpgrp: new pgrp and pid != pgid");
+#endif
                MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
                       M_WAITOK);
                if (mksess) {
                        register struct session *sess;
                MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
                       M_WAITOK);
                if (mksess) {
                        register struct session *sess;
+
                        /*
                         * new session
                         */
                        /*
                         * new session
                         */
@@ -140,75 +131,73 @@ pgmv(p, pgid, mksess)
                                M_SESSION, M_WAITOK);
                        sess->s_leader = p;
                        sess->s_count = 1;
                                M_SESSION, M_WAITOK);
                        sess->s_leader = p;
                        sess->s_count = 1;
+                       sess->s_ttyvp = NULL;
+                       sess->s_ttyp = NULL;
+                       bcopy(p->p_session->s_login, sess->s_login,
+                           sizeof(sess->s_login));
+                       p->p_flag &= ~SCTTY;
                        pgrp->pg_session = sess;
                        pgrp->pg_session = sess;
-                       if (p != u.u_procp)
-                               panic("pgmv: mksession and p != u.u_procp");
-                       u.u_ttyp = 0;
-                       u.u_ttyd = 0;
+#ifdef DIAGNOSTIC
+                       if (p != curproc)
+                               panic("enterpgrp: mksession and p != curproc");
+#endif
                } else {
                        pgrp->pg_session = p->p_session;
                        pgrp->pg_session->s_count++;
                }
                pgrp->pg_id = pgid;
                } else {
                        pgrp->pg_session = p->p_session;
                        pgrp->pg_session->s_count++;
                }
                pgrp->pg_id = pgid;
-               pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)];
+               pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
                pgrphash[n] = pgrp;
                pgrp->pg_jobc = 0;
                pgrphash[n] = pgrp;
                pgrp->pg_jobc = 0;
-               pgrp->pg_mem = 0;
-       }
+               pgrp->pg_mem = NULL;
+       } else if (pgrp == p->p_pgrp)
+               return;
+
        /*
        /*
-        * adjust eligibility of affected pgrps to participate in job control
+        * Adjust eligibility of affected pgrps to participate in job control.
+        * Increment eligibility counts before decrementing, otherwise we
+        * could reach 0 spuriously during the first call.
         */
         */
-       if (PGRP_JOBC(p))
-               p->p_pgrp->pg_jobc--;
-       for (cp = p->p_cptr; cp; cp = cp->p_osptr)
-               if (PGRP_JOBC(cp))
-                       cp->p_pgrp->pg_jobc--;
+       fixjobc(p, pgrp, 1);
+       fixjobc(p, p->p_pgrp, 0);
+
        /*
         * unlink p from old process group
         */
        /*
         * unlink p from old process group
         */
-       for (; *pp; pp = &(*pp)->p_pgrpnxt)
+       for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
                if (*pp == p) {
                        *pp = p->p_pgrpnxt;
                        goto done;
                }
                if (*pp == p) {
                        *pp = p->p_pgrpnxt;
                        goto done;
                }
-       panic("pgmv: can't find p on old pgrp\n");
+       panic("enterpgrp: can't find p on old pgrp");
 done:
 done:
+       /*
+        * delete old if empty
+        */
+       if (p->p_pgrp->pg_mem == 0)
+               pgdelete(p->p_pgrp);
        /*
         * link into new one
         */
        /*
         * link into new one
         */
+       p->p_pgrp = pgrp;
        p->p_pgrpnxt = pgrp->pg_mem;
        pgrp->pg_mem = p;
        p->p_pgrpnxt = pgrp->pg_mem;
        pgrp->pg_mem = p;
-       p->p_pgrp = pgrp;
-       /*
-        * adjust eligibility of affected pgrps to participate in job control
-        */
-       if (PGRP_JOBC(p))
-               p->p_pgrp->pg_jobc++;
-       for (cp = p->p_cptr; cp; cp = cp->p_osptr)
-               if (PGRP_JOBC(cp))
-                       cp->p_pgrp->pg_jobc++;
-       /*
-        * old pgrp empty?
-        */
-       if (!p->p_pgrp->pg_mem)
-               pgdelete(p->p_pgrp);
 }
 
 /*
  * remove process from process group
  */
 }
 
 /*
  * remove process from process group
  */
-pgrm(p)
+leavepgrp(p)
        register struct proc *p;
 {
        register struct proc **pp = &p->p_pgrp->pg_mem;
        register struct proc *p;
 {
        register struct proc **pp = &p->p_pgrp->pg_mem;
-       register struct proc *cp;
 
        for (; *pp; pp = &(*pp)->p_pgrpnxt)
                if (*pp == p) {
                        *pp = p->p_pgrpnxt;
                        goto done;
                }
 
        for (; *pp; pp = &(*pp)->p_pgrpnxt)
                if (*pp == p) {
                        *pp = p->p_pgrpnxt;
                        goto done;
                }
-       panic("pgrm: can't find p in pgrp\n");
+       panic("leavepgrp: can't find p in pgrp");
 done:
        if (!p->p_pgrp->pg_mem)
                pgdelete(p->p_pgrp);
 done:
        if (!p->p_pgrp->pg_mem)
                pgdelete(p->p_pgrp);
@@ -223,45 +212,90 @@ pgdelete(pgrp)
 {
        register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
 
 {
        register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
 
+       if (pgrp->pg_session->s_ttyp != NULL && 
+           pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
+               pgrp->pg_session->s_ttyp->t_pgrp = NULL;
        for (; *pgp; pgp = &(*pgp)->pg_hforw)
                if (*pgp == pgrp) {
                        *pgp = pgrp->pg_hforw;
                        goto done;
                }
        for (; *pgp; pgp = &(*pgp)->pg_hforw)
                if (*pgp == pgrp) {
                        *pgp = pgrp->pg_hforw;
                        goto done;
                }
-       panic("pgdelete: can't find pgrp on hash chain\n");
+       panic("pgdelete: can't find pgrp on hash chain");
 done:
        if (--pgrp->pg_session->s_count == 0)
                FREE(pgrp->pg_session, M_SESSION);
        FREE(pgrp, M_PGRP);
 }
 
 done:
        if (--pgrp->pg_session->s_count == 0)
                FREE(pgrp->pg_session, M_SESSION);
        FREE(pgrp, M_PGRP);
 }
 
+static orphanpg();
+
 /*
 /*
- * init the process queues
+ * Adjust pgrp jobc counters when specified process changes process group.
+ * We count the number of processes in each process group that "qualify"
+ * the group for terminal job control (those with a parent in a different
+ * process group of the same session).  If that count reaches zero, the
+ * process group becomes orphaned.  Check both the specified process'
+ * process group and that of its children.
+ * entering == 0 => p is leaving specified group.
+ * entering == 1 => p is entering specified group.
  */
  */
-pqinit()
-{
+fixjobc(p, pgrp, entering)
        register struct proc *p;
        register struct proc *p;
+       register struct pgrp *pgrp;
+       int entering;
+{
+       register struct pgrp *hispgrp;
+       register struct session *mysession = pgrp->pg_session;
 
        /*
 
        /*
-        * most procs are initially on freequeue
-        *      nb: we place them there in their "natural" order.
+        * Check p's parent to see whether p qualifies its own process
+        * group; if so, adjust count for p's process group.
         */
         */
-
-       freeproc = NULL;
-       for (p = procNPROC; --p > proc; freeproc = p)
-               p->p_nxt = freeproc;
+       if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
+           hispgrp->pg_session == mysession)
+               if (entering)
+                       pgrp->pg_jobc++;
+               else if (--pgrp->pg_jobc == 0)
+                       orphanpg(pgrp);
 
        /*
 
        /*
-        * but proc[0] is special ...
+        * Check this process' children to see whether they qualify
+        * their process groups; if so, adjust counts for children's
+        * process groups.
         */
         */
+       for (p = p->p_cptr; p; p = p->p_osptr)
+               if ((hispgrp = p->p_pgrp) != pgrp &&
+                   hispgrp->pg_session == mysession &&
+                   p->p_stat != SZOMB)
+                       if (entering)
+                               hispgrp->pg_jobc++;
+                       else if (--hispgrp->pg_jobc == 0)
+                               orphanpg(hispgrp);
+}
 
 
-       allproc = p;
-       p->p_nxt = NULL;
-       p->p_prev = &allproc;
+/* 
+ * A process group has become orphaned;
+ * if there are any stopped processes in the group,
+ * hang-up all process in that group.
+ */
+static
+orphanpg(pg)
+       struct pgrp *pg;
+{
+       register struct proc *p;
 
 
-       zombproc = NULL;
+       for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
+               if (p->p_stat == SSTOP) {
+                       for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
+                               psignal(p, SIGHUP);
+                               psignal(p, SIGCONT);
+                       }
+                       return;
+               }
+       }
 }
 
 }
 
+#ifdef debug
 /* DEBUG */
 pgrpdump()
 {
 /* DEBUG */
 pgrpdump()
 {
@@ -285,3 +319,4 @@ pgrpdump()
                }
        }
 }
                }
        }
 }
+#endif /* debug */