xref: /original-bsd/sys/kern/kern_proc.c (revision 80855e64)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_proc.c	7.15 (Berkeley) 04/20/91
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "kernel.h"
14 #include "proc.h"
15 #include "buf.h"
16 #include "seg.h"
17 #include "acct.h"
18 #include "wait.h"
19 #include "file.h"
20 #include "../ufs/quota.h"
21 #include "uio.h"
22 #include "malloc.h"
23 #include "mbuf.h"
24 #include "ioctl.h"
25 #include "tty.h"
26 
27 /*
28  * Is p an inferior of the current process?
29  */
30 inferior(p)
31 	register struct proc *p;
32 {
33 
34 	for (; p != curproc; p = p->p_pptr)
35 		if (p->p_pid == 0)
36 			return (0);
37 	return (1);
38 }
39 
40 /*
41  * Locate a process by number
42  */
43 struct proc *
44 pfind(pid)
45 	register pid;
46 {
47 	register struct proc *p = pidhash[PIDHASH(pid)];
48 
49 	for (; p; p = p->p_hash)
50 		if (p->p_pid == pid)
51 			return (p);
52 	return ((struct proc *)0);
53 }
54 
55 /*
56  * Locate a process group by number
57  */
58 struct pgrp *
59 pgfind(pgid)
60 	register pid_t pgid;
61 {
62 	register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
63 
64 	for (; pgrp; pgrp = pgrp->pg_hforw)
65 		if (pgrp->pg_id == pgid)
66 			return (pgrp);
67 	return ((struct pgrp *)0);
68 }
69 
70 /*
71  * Move p to a new or existing process group (and session)
72  */
73 enterpgrp(p, pgid, mksess)
74 	register struct proc *p;
75 	pid_t pgid;
76 {
77 	register struct pgrp *pgrp = pgfind(pgid);
78 	register struct proc **pp;
79 	register struct proc *cp;
80 	int n;
81 
82 #ifdef DIAGNOSTIC
83 	if (pgrp && mksess)	/* firewalls */
84 		panic("enterpgrp: setsid into non-empty pgrp");
85 	if (SESS_LEADER(p))
86 		panic("enterpgrp: session leader attempted setpgrp");
87 #endif
88 	if (pgrp == NULL) {
89 		/*
90 		 * new process group
91 		 */
92 #ifdef DIAGNOSTIC
93 		if (p->p_pid != pgid)
94 			panic("enterpgrp: new pgrp and pid != pgid");
95 #endif
96 		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
97 		       M_WAITOK);
98 		if (mksess) {
99 			register struct session *sess;
100 			/*
101 			 * new session
102 			 */
103 			MALLOC(sess, struct session *, sizeof(struct session),
104 				M_SESSION, M_WAITOK);
105 			sess->s_leader = p;
106 			sess->s_count = 1;
107 			sess->s_ttyvp = NULL;
108 			sess->s_ttyp = NULL;
109 			p->p_flag &= ~SCTTY;
110 			pgrp->pg_session = sess;
111 #ifdef DIAGNOSTIC
112 			if (p != curproc)
113 				panic("enterpgrp: mksession and p != curproc");
114 #endif
115 		} else {
116 			pgrp->pg_session = p->p_session;
117 			pgrp->pg_session->s_count++;
118 		}
119 		pgrp->pg_id = pgid;
120 		pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
121 		pgrphash[n] = pgrp;
122 		pgrp->pg_jobc = 0;
123 		pgrp->pg_mem = NULL;
124 	} else if (pgrp == p->p_pgrp)
125 		return;
126 
127 	/*
128 	 * Adjust eligibility of affected pgrps to participate in job control.
129 	 * Increment eligibility counts before decrementing, otherwise we
130 	 * could reach 0 spuriously during the first call.
131 	 */
132 	fixjobc(p, pgrp, 1);
133 	fixjobc(p, p->p_pgrp, 0);
134 
135 	/*
136 	 * unlink p from old process group
137 	 */
138 	for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
139 		if (*pp == p) {
140 			*pp = p->p_pgrpnxt;
141 			goto done;
142 		}
143 	panic("enterpgrp: can't find p on old pgrp");
144 done:
145 	/*
146 	 * delete old if empty
147 	 */
148 	if (p->p_pgrp->pg_mem == 0)
149 		pgdelete(p->p_pgrp);
150 	/*
151 	 * link into new one
152 	 */
153 	p->p_pgrp = pgrp;
154 	p->p_pgrpnxt = pgrp->pg_mem;
155 	pgrp->pg_mem = p;
156 }
157 
158 /*
159  * remove process from process group
160  */
161 leavepgrp(p)
162 	register struct proc *p;
163 {
164 	register struct proc **pp = &p->p_pgrp->pg_mem;
165 
166 	for (; *pp; pp = &(*pp)->p_pgrpnxt)
167 		if (*pp == p) {
168 			*pp = p->p_pgrpnxt;
169 			goto done;
170 		}
171 	panic("leavepgrp: can't find p in pgrp");
172 done:
173 	if (!p->p_pgrp->pg_mem)
174 		pgdelete(p->p_pgrp);
175 	p->p_pgrp = 0;
176 }
177 
178 /*
179  * delete a process group
180  */
181 pgdelete(pgrp)
182 	register struct pgrp *pgrp;
183 {
184 	register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
185 
186 	if (pgrp->pg_session->s_ttyp != NULL &&
187 	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
188 		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
189 	for (; *pgp; pgp = &(*pgp)->pg_hforw)
190 		if (*pgp == pgrp) {
191 			*pgp = pgrp->pg_hforw;
192 			goto done;
193 		}
194 	panic("pgdelete: can't find pgrp on hash chain");
195 done:
196 	if (--pgrp->pg_session->s_count == 0)
197 		FREE(pgrp->pg_session, M_SESSION);
198 	FREE(pgrp, M_PGRP);
199 }
200 
201 static orphanpg();
202 
203 /*
204  * Adjust pgrp jobc counters when specified process changes process group.
205  * We count the number of processes in each process group that "qualify"
206  * the group for terminal job control (those with a parent in a different
207  * process group of the same session).  If that count reaches zero, the
208  * process group becomes orphaned.  Check both the specified process'
209  * process group and that of its children.
210  * entering == 0 => p is leaving specified group.
211  * entering == 1 => p is entering specified group.
212  */
213 fixjobc(p, pgrp, entering)
214 	register struct proc *p;
215 	register struct pgrp *pgrp;
216 	int entering;
217 {
218 	register struct pgrp *hispgrp;
219 	register struct session *mysession = pgrp->pg_session;
220 
221 	/*
222 	 * Check p's parent to see whether p qualifies its own process
223 	 * group; if so, adjust count for p's process group.
224 	 */
225 	if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
226 	    hispgrp->pg_session == mysession)
227 		if (entering)
228 			pgrp->pg_jobc++;
229 		else if (--pgrp->pg_jobc == 0)
230 			orphanpg(pgrp);
231 
232 	/*
233 	 * Check this process' children to see whether they qualify
234 	 * their process groups; if so, adjust counts for children's
235 	 * process groups.
236 	 */
237 	for (p = p->p_cptr; p; p = p->p_osptr)
238 		if ((hispgrp = p->p_pgrp) != pgrp &&
239 		    hispgrp->pg_session == mysession &&
240 		    p->p_stat != SZOMB)
241 			if (entering)
242 				hispgrp->pg_jobc++;
243 			else if (--hispgrp->pg_jobc == 0)
244 				orphanpg(hispgrp);
245 }
246 
247 /*
248  * A process group has become orphaned;
249  * if there are any stopped processes in the group,
250  * hang-up all process in that group.
251  */
252 static
253 orphanpg(pg)
254 	struct pgrp *pg;
255 {
256 	register struct proc *p;
257 
258 	for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
259 		if (p->p_stat == SSTOP) {
260 			for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
261 				psignal(p, SIGHUP);
262 				psignal(p, SIGCONT);
263 			}
264 			return;
265 		}
266 	}
267 }
268 
269 #ifdef debug
270 /* DEBUG */
271 pgrpdump()
272 {
273 	register struct pgrp *pgrp;
274 	register struct proc *p;
275 	register i;
276 
277 	for (i=0; i<PIDHSZ; i++) {
278 		if (pgrphash[i]) {
279 		  printf("\tindx %d\n", i);
280 		  for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
281 		    printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
282 			pgrp, pgrp->pg_id, pgrp->pg_session,
283 			pgrp->pg_session->s_count, pgrp->pg_mem);
284 		    for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
285 			printf("\t\tpid %d addr %x pgrp %x\n",
286 				p->p_pid, p, p->p_pgrp);
287 		    }
288 		  }
289 
290 		}
291 	}
292 }
293 #endif /* debug */
294