386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Wed, 22 Jan 1992 05:29:38 +0000 (21:29 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Wed, 22 Jan 1992 05:29:38 +0000 (21:29 -0800)
Work on file usr/src/sys.386bsd/kern/kern_proc.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/sys.386bsd/kern/kern_proc.c [new file with mode: 0644]

diff --git a/usr/src/sys.386bsd/kern/kern_proc.c b/usr/src/sys.386bsd/kern/kern_proc.c
new file mode 100644 (file)
index 0000000..8b0403c
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ * 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 "param.h"
+#include "systm.h"
+#include "kernel.h"
+#include "proc.h"
+#include "buf.h"
+#include "acct.h"
+#include "wait.h"
+#include "file.h"
+#include "../ufs/quota.h"
+#include "uio.h"
+#include "malloc.h"
+#include "mbuf.h"
+#include "ioctl.h"
+#include "tty.h"
+
+/*
+ * Is p an inferior of the current process?
+ */
+inferior(p)
+       register struct proc *p;
+{
+
+       for (; p != curproc; p = p->p_pptr)
+               if (p->p_pid == 0)
+                       return (0);
+       return (1);
+}
+
+/*
+ * Locate a process by number
+ */
+struct proc *
+pfind(pid)
+       register pid;
+{
+       register struct proc *p = pidhash[PIDHASH(pid)];
+
+       for (; p; p = p->p_hash)
+               if (p->p_pid == pid)
+                       return (p);
+       return ((struct proc *)0);
+}
+
+/*
+ * Locate a process group by number
+ */
+struct pgrp *
+pgfind(pgid)
+       register pid_t pgid;
+{
+       register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
+
+       for (; pgrp; pgrp = pgrp->pg_hforw)
+               if (pgrp->pg_id == pgid)
+                       return (pgrp);
+       return ((struct pgrp *)0);
+}
+
+/*
+ * Move p to a new or existing process group (and session)
+ */
+enterpgrp(p, pgid, mksess)
+       register struct proc *p;
+       pid_t pgid;
+{
+       register struct pgrp *pgrp = pgfind(pgid);
+       register struct proc **pp;
+       register struct proc *cp;
+       int n;
+
+#ifdef DIAGNOSTIC
+       if (pgrp && mksess)     /* firewalls */
+               panic("enterpgrp: setsid into non-empty pgrp");
+       if (SESS_LEADER(p))
+               panic("enterpgrp: session leader attempted setpgrp");
+#endif
+       if (pgrp == NULL) {
+               /*
+                * new process group
+                */
+#ifdef DIAGNOSTIC
+               if (p->p_pid != pgid)
+                       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;
+
+                       /*
+                        * new session
+                        */
+                       MALLOC(sess, struct session *, sizeof(struct session),
+                               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;
+#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;
+               pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
+               pgrphash[n] = pgrp;
+               pgrp->pg_jobc = 0;
+               pgrp->pg_mem = NULL;
+       } else if (pgrp == p->p_pgrp)
+               return;
+
+       /*
+        * 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.
+        */
+       fixjobc(p, pgrp, 1);
+       fixjobc(p, p->p_pgrp, 0);
+
+       /*
+        * unlink p from old process group
+        */
+       for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
+               if (*pp == p) {
+                       *pp = p->p_pgrpnxt;
+                       goto done;
+               }
+       panic("enterpgrp: can't find p on old pgrp");
+done:
+       /*
+        * delete old if empty
+        */
+       if (p->p_pgrp->pg_mem == 0)
+               pgdelete(p->p_pgrp);
+       /*
+        * link into new one
+        */
+       p->p_pgrp = pgrp;
+       p->p_pgrpnxt = pgrp->pg_mem;
+       pgrp->pg_mem = p;
+}
+
+/*
+ * remove process from process group
+ */
+leavepgrp(p)
+       register struct proc *p;
+{
+       register struct proc **pp = &p->p_pgrp->pg_mem;
+
+       for (; *pp; pp = &(*pp)->p_pgrpnxt)
+               if (*pp == p) {
+                       *pp = p->p_pgrpnxt;
+                       goto done;
+               }
+       panic("leavepgrp: can't find p in pgrp");
+done:
+       if (!p->p_pgrp->pg_mem)
+               pgdelete(p->p_pgrp);
+       p->p_pgrp = 0;
+}
+
+/*
+ * delete a process group
+ */
+pgdelete(pgrp)
+       register struct pgrp *pgrp;
+{
+       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;
+               }
+       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);
+}
+
+static orphanpg();
+
+/*
+ * 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.
+ */
+fixjobc(p, pgrp, entering)
+       register struct proc *p;
+       register struct pgrp *pgrp;
+       int entering;
+{
+       register struct pgrp *hispgrp;
+       register struct session *mysession = pgrp->pg_session;
+
+       /*
+        * Check p's parent to see whether p qualifies its own process
+        * group; if so, adjust count for p's process group.
+        */
+       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);
+
+       /*
+        * 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);
+}
+
+/* 
+ * 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;
+
+       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()
+{
+       register struct pgrp *pgrp;
+       register struct proc *p;
+       register i;
+
+       for (i=0; i<PIDHSZ; i++) {
+               if (pgrphash[i]) {
+                 printf("\tindx %d\n", i);
+                 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
+                   printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
+                       pgrp, pgrp->pg_id, pgrp->pg_session,
+                       pgrp->pg_session->s_count, pgrp->pg_mem);
+                   for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
+                       printf("\t\tpid %d addr %x pgrp %x\n", 
+                               p->p_pid, p, p->p_pgrp);
+                   }
+                 }
+
+               }
+       }
+}
+#endif /* debug */