xref: /csrg-svn/sys/kern/kern_proc.c (revision 50252)
123371Smckusick /*
248417Skarels  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
337728Smckusick  * All rights reserved.
423371Smckusick  *
544438Sbostic  * %sccs.include.redist.c%
637728Smckusick  *
7*50252Skarels  *	@(#)kern_proc.c	7.16 (Berkeley) 06/28/91
823371Smckusick  */
936Sbill 
1017091Sbloom #include "param.h"
1117091Sbloom #include "systm.h"
1217091Sbloom #include "map.h"
1317091Sbloom #include "kernel.h"
1417091Sbloom #include "proc.h"
1517091Sbloom #include "buf.h"
1617091Sbloom #include "seg.h"
1717091Sbloom #include "acct.h"
1817091Sbloom #include "wait.h"
1917091Sbloom #include "file.h"
2037728Smckusick #include "../ufs/quota.h"
2117091Sbloom #include "uio.h"
2235810Smarc #include "malloc.h"
2317091Sbloom #include "mbuf.h"
2439064Smarc #include "ioctl.h"
2535810Smarc #include "tty.h"
2636Sbill 
2717540Skarels /*
287497Sroot  * Is p an inferior of the current process?
2936Sbill  */
307497Sroot inferior(p)
317816Sroot 	register struct proc *p;
3236Sbill {
3345673Skarels 
3447542Skarels 	for (; p != curproc; p = p->p_pptr)
3547542Skarels 		if (p->p_pid == 0)
367497Sroot 			return (0);
377497Sroot 	return (1);
3836Sbill }
397816Sroot 
4040709Skarels /*
4140709Skarels  * Locate a process by number
4240709Skarels  */
437816Sroot struct proc *
447816Sroot pfind(pid)
4535810Smarc 	register pid;
467816Sroot {
4740709Skarels 	register struct proc *p = pidhash[PIDHASH(pid)];
487816Sroot 
4940709Skarels 	for (; p; p = p->p_hash)
507816Sroot 		if (p->p_pid == pid)
517816Sroot 			return (p);
527816Sroot 	return ((struct proc *)0);
537816Sroot }
5416529Skarels 
5516529Skarels /*
5635810Smarc  * Locate a process group by number
5735810Smarc  */
5835810Smarc struct pgrp *
5935810Smarc pgfind(pgid)
6035810Smarc 	register pid_t pgid;
6135810Smarc {
6235810Smarc 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
6335810Smarc 
6435810Smarc 	for (; pgrp; pgrp = pgrp->pg_hforw)
6535810Smarc 		if (pgrp->pg_id == pgid)
6640709Skarels 			return (pgrp);
6735810Smarc 	return ((struct pgrp *)0);
6835810Smarc }
6935810Smarc 
7035810Smarc /*
7135810Smarc  * Move p to a new or existing process group (and session)
7235810Smarc  */
7347542Skarels enterpgrp(p, pgid, mksess)
7435810Smarc 	register struct proc *p;
7535810Smarc 	pid_t pgid;
7635810Smarc {
7735810Smarc 	register struct pgrp *pgrp = pgfind(pgid);
7845673Skarels 	register struct proc **pp;
7935810Smarc 	register struct proc *cp;
8045673Skarels 	int n;
8135810Smarc 
8239562Smarc #ifdef DIAGNOSTIC
8335810Smarc 	if (pgrp && mksess)	/* firewalls */
8447542Skarels 		panic("enterpgrp: setsid into non-empty pgrp");
8535810Smarc 	if (SESS_LEADER(p))
8647542Skarels 		panic("enterpgrp: session leader attempted setpgrp");
8739562Smarc #endif
8837589Smarc 	if (pgrp == NULL) {
8935810Smarc 		/*
9035810Smarc 		 * new process group
9135810Smarc 		 */
9239562Smarc #ifdef DIAGNOSTIC
9335810Smarc 		if (p->p_pid != pgid)
9447542Skarels 			panic("enterpgrp: new pgrp and pid != pgid");
9539562Smarc #endif
9635810Smarc 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
9735810Smarc 		       M_WAITOK);
9835810Smarc 		if (mksess) {
9935810Smarc 			register struct session *sess;
100*50252Skarels 
10135810Smarc 			/*
10235810Smarc 			 * new session
10335810Smarc 			 */
10435810Smarc 			MALLOC(sess, struct session *, sizeof(struct session),
10535810Smarc 				M_SESSION, M_WAITOK);
10635810Smarc 			sess->s_leader = p;
10735810Smarc 			sess->s_count = 1;
10839562Smarc 			sess->s_ttyvp = NULL;
10939562Smarc 			sess->s_ttyp = NULL;
110*50252Skarels 			bcopy(p->p_session->s_login, sess->s_login,
111*50252Skarels 			    sizeof(sess->s_login));
11239562Smarc 			p->p_flag &= ~SCTTY;
11335810Smarc 			pgrp->pg_session = sess;
11439562Smarc #ifdef DIAGNOSTIC
11547542Skarels 			if (p != curproc)
11647542Skarels 				panic("enterpgrp: mksession and p != curproc");
11739562Smarc #endif
11835810Smarc 		} else {
11935810Smarc 			pgrp->pg_session = p->p_session;
12035810Smarc 			pgrp->pg_session->s_count++;
12135810Smarc 		}
12235810Smarc 		pgrp->pg_id = pgid;
12345673Skarels 		pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
12435810Smarc 		pgrphash[n] = pgrp;
12535810Smarc 		pgrp->pg_jobc = 0;
12639562Smarc 		pgrp->pg_mem = NULL;
12744387Smarc 	} else if (pgrp == p->p_pgrp)
12844387Smarc 		return;
12945673Skarels 
13035810Smarc 	/*
13145673Skarels 	 * Adjust eligibility of affected pgrps to participate in job control.
13245673Skarels 	 * Increment eligibility counts before decrementing, otherwise we
13345673Skarels 	 * could reach 0 spuriously during the first call.
13435810Smarc 	 */
13545673Skarels 	fixjobc(p, pgrp, 1);
13645673Skarels 	fixjobc(p, p->p_pgrp, 0);
13745673Skarels 
13835810Smarc 	/*
13935810Smarc 	 * unlink p from old process group
14035810Smarc 	 */
14145673Skarels 	for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
14235810Smarc 		if (*pp == p) {
14335810Smarc 			*pp = p->p_pgrpnxt;
14435810Smarc 			goto done;
14535810Smarc 		}
14647542Skarels 	panic("enterpgrp: can't find p on old pgrp");
14735810Smarc done:
14835810Smarc 	/*
14945673Skarels 	 * delete old if empty
15045673Skarels 	 */
15145673Skarels 	if (p->p_pgrp->pg_mem == 0)
15245673Skarels 		pgdelete(p->p_pgrp);
15345673Skarels 	/*
15435810Smarc 	 * link into new one
15535810Smarc 	 */
15645673Skarels 	p->p_pgrp = pgrp;
15735810Smarc 	p->p_pgrpnxt = pgrp->pg_mem;
15835810Smarc 	pgrp->pg_mem = p;
15935810Smarc }
16035810Smarc 
16135810Smarc /*
16235810Smarc  * remove process from process group
16335810Smarc  */
16447542Skarels leavepgrp(p)
16535810Smarc 	register struct proc *p;
16635810Smarc {
16735810Smarc 	register struct proc **pp = &p->p_pgrp->pg_mem;
16835810Smarc 
16935810Smarc 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
17035810Smarc 		if (*pp == p) {
17135810Smarc 			*pp = p->p_pgrpnxt;
17235810Smarc 			goto done;
17335810Smarc 		}
17447542Skarels 	panic("leavepgrp: can't find p in pgrp");
17535810Smarc done:
17635810Smarc 	if (!p->p_pgrp->pg_mem)
17735810Smarc 		pgdelete(p->p_pgrp);
17835810Smarc 	p->p_pgrp = 0;
17935810Smarc }
18035810Smarc 
18135810Smarc /*
18235810Smarc  * delete a process group
18335810Smarc  */
18435810Smarc pgdelete(pgrp)
18535810Smarc 	register struct pgrp *pgrp;
18635810Smarc {
18735810Smarc 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
18835810Smarc 
18939562Smarc 	if (pgrp->pg_session->s_ttyp != NULL &&
19039562Smarc 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
19139562Smarc 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
19235810Smarc 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
19335810Smarc 		if (*pgp == pgrp) {
19435810Smarc 			*pgp = pgrp->pg_hforw;
19535810Smarc 			goto done;
19635810Smarc 		}
19737589Smarc 	panic("pgdelete: can't find pgrp on hash chain");
19835810Smarc done:
19935810Smarc 	if (--pgrp->pg_session->s_count == 0)
20035810Smarc 		FREE(pgrp->pg_session, M_SESSION);
20135810Smarc 	FREE(pgrp, M_PGRP);
20235810Smarc }
20335810Smarc 
20448417Skarels static orphanpg();
20548417Skarels 
20635810Smarc /*
20745673Skarels  * Adjust pgrp jobc counters when specified process changes process group.
20845673Skarels  * We count the number of processes in each process group that "qualify"
20945673Skarels  * the group for terminal job control (those with a parent in a different
21045673Skarels  * process group of the same session).  If that count reaches zero, the
21145673Skarels  * process group becomes orphaned.  Check both the specified process'
21245673Skarels  * process group and that of its children.
21345673Skarels  * entering == 0 => p is leaving specified group.
21445673Skarels  * entering == 1 => p is entering specified group.
21544387Smarc  */
21645673Skarels fixjobc(p, pgrp, entering)
21744387Smarc 	register struct proc *p;
21845673Skarels 	register struct pgrp *pgrp;
21945673Skarels 	int entering;
22044387Smarc {
22145673Skarels 	register struct pgrp *hispgrp;
22245673Skarels 	register struct session *mysession = pgrp->pg_session;
22344387Smarc 
22445673Skarels 	/*
22545673Skarels 	 * Check p's parent to see whether p qualifies its own process
22645673Skarels 	 * group; if so, adjust count for p's process group.
22745673Skarels 	 */
22845673Skarels 	if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
22944387Smarc 	    hispgrp->pg_session == mysession)
23045673Skarels 		if (entering)
23145673Skarels 			pgrp->pg_jobc++;
23245673Skarels 		else if (--pgrp->pg_jobc == 0)
23345673Skarels 			orphanpg(pgrp);
23444387Smarc 
23545673Skarels 	/*
23645673Skarels 	 * Check this process' children to see whether they qualify
23745673Skarels 	 * their process groups; if so, adjust counts for children's
23845673Skarels 	 * process groups.
23945673Skarels 	 */
24045673Skarels 	for (p = p->p_cptr; p; p = p->p_osptr)
24145673Skarels 		if ((hispgrp = p->p_pgrp) != pgrp &&
24244387Smarc 		    hispgrp->pg_session == mysession &&
24344387Smarc 		    p->p_stat != SZOMB)
24445673Skarels 			if (entering)
24544387Smarc 				hispgrp->pg_jobc++;
24645673Skarels 			else if (--hispgrp->pg_jobc == 0)
24745673Skarels 				orphanpg(hispgrp);
24845673Skarels }
24944387Smarc 
25045673Skarels /*
25145673Skarels  * A process group has become orphaned;
25245673Skarels  * if there are any stopped processes in the group,
25345673Skarels  * hang-up all process in that group.
25445673Skarels  */
25545673Skarels static
25645673Skarels orphanpg(pg)
25745673Skarels 	struct pgrp *pg;
25845673Skarels {
25945673Skarels 	register struct proc *p;
26045673Skarels 
26145673Skarels 	for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
26245673Skarels 		if (p->p_stat == SSTOP) {
26345673Skarels 			for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
26445673Skarels 				psignal(p, SIGHUP);
26545673Skarels 				psignal(p, SIGCONT);
26644387Smarc 			}
26745673Skarels 			return;
26845673Skarels 		}
26945673Skarels 	}
27044387Smarc }
27145673Skarels 
27237728Smckusick #ifdef debug
27335810Smarc /* DEBUG */
27435810Smarc pgrpdump()
27535810Smarc {
27635810Smarc 	register struct pgrp *pgrp;
27735810Smarc 	register struct proc *p;
27835810Smarc 	register i;
27935810Smarc 
28035810Smarc 	for (i=0; i<PIDHSZ; i++) {
28135810Smarc 		if (pgrphash[i]) {
28235810Smarc 		  printf("\tindx %d\n", i);
28335810Smarc 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
28435810Smarc 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
28535810Smarc 			pgrp, pgrp->pg_id, pgrp->pg_session,
28635810Smarc 			pgrp->pg_session->s_count, pgrp->pg_mem);
28735810Smarc 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
28835810Smarc 			printf("\t\tpid %d addr %x pgrp %x\n",
28935810Smarc 				p->p_pid, p, p->p_pgrp);
29035810Smarc 		    }
29135810Smarc 		  }
29235810Smarc 
29335810Smarc 		}
29435810Smarc 	}
29535810Smarc }
29637728Smckusick #endif /* debug */
297