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