kern_proc.c revision 1.2 1 /*
2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)kern_proc.c 7.16 (Berkeley) 6/28/91
34 * $Id: kern_proc.c,v 1.2 1993/05/18 18:19:17 cgd Exp $
35 */
36
37 #include "param.h"
38 #include "systm.h"
39 #include "kernel.h"
40 #include "proc.h"
41 #include "buf.h"
42 #include "acct.h"
43 #include "wait.h"
44 #include "file.h"
45 #include "../ufs/quota.h"
46 #include "uio.h"
47 #include "malloc.h"
48 #include "mbuf.h"
49 #include "ioctl.h"
50 #include "select.h"
51 #include "tty.h"
52
53 /*
54 * Is p an inferior of the current process?
55 */
56 inferior(p)
57 register struct proc *p;
58 {
59
60 for (; p != curproc; p = p->p_pptr)
61 if (p->p_pid == 0)
62 return (0);
63 return (1);
64 }
65
66 /*
67 * Locate a process by number
68 */
69 struct proc *
70 pfind(pid)
71 register pid;
72 {
73 register struct proc *p = pidhash[PIDHASH(pid)];
74
75 for (; p; p = p->p_hash)
76 if (p->p_pid == pid)
77 return (p);
78 return ((struct proc *)0);
79 }
80
81 /*
82 * Locate a process group by number
83 */
84 struct pgrp *
85 pgfind(pgid)
86 register pid_t pgid;
87 {
88 register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
89
90 for (; pgrp; pgrp = pgrp->pg_hforw)
91 if (pgrp->pg_id == pgid)
92 return (pgrp);
93 return ((struct pgrp *)0);
94 }
95
96 /*
97 * Move p to a new or existing process group (and session)
98 */
99 enterpgrp(p, pgid, mksess)
100 register struct proc *p;
101 pid_t pgid;
102 {
103 register struct pgrp *pgrp = pgfind(pgid);
104 register struct proc **pp;
105 register struct proc *cp;
106 int n;
107
108 #ifdef DIAGNOSTIC
109 if (pgrp && mksess) /* firewalls */
110 panic("enterpgrp: setsid into non-empty pgrp");
111 if (SESS_LEADER(p))
112 panic("enterpgrp: session leader attempted setpgrp");
113 #endif
114 if (pgrp == NULL) {
115 /*
116 * new process group
117 */
118 #ifdef DIAGNOSTIC
119 if (p->p_pid != pgid)
120 panic("enterpgrp: new pgrp and pid != pgid");
121 #endif
122 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
123 M_WAITOK);
124 if (mksess) {
125 register struct session *sess;
126
127 /*
128 * new session
129 */
130 MALLOC(sess, struct session *, sizeof(struct session),
131 M_SESSION, M_WAITOK);
132 sess->s_leader = p;
133 sess->s_count = 1;
134 sess->s_ttyvp = NULL;
135 sess->s_ttyp = NULL;
136 bcopy(p->p_session->s_login, sess->s_login,
137 sizeof(sess->s_login));
138 p->p_flag &= ~SCTTY;
139 pgrp->pg_session = sess;
140 #ifdef DIAGNOSTIC
141 if (p != curproc)
142 panic("enterpgrp: mksession and p != curproc");
143 #endif
144 } else {
145 pgrp->pg_session = p->p_session;
146 pgrp->pg_session->s_count++;
147 }
148 pgrp->pg_id = pgid;
149 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
150 pgrphash[n] = pgrp;
151 pgrp->pg_jobc = 0;
152 pgrp->pg_mem = NULL;
153 } else if (pgrp == p->p_pgrp)
154 return;
155
156 /*
157 * Adjust eligibility of affected pgrps to participate in job control.
158 * Increment eligibility counts before decrementing, otherwise we
159 * could reach 0 spuriously during the first call.
160 */
161 fixjobc(p, pgrp, 1);
162 fixjobc(p, p->p_pgrp, 0);
163
164 /*
165 * unlink p from old process group
166 */
167 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
168 if (*pp == p) {
169 *pp = p->p_pgrpnxt;
170 goto done;
171 }
172 panic("enterpgrp: can't find p on old pgrp");
173 done:
174 /*
175 * delete old if empty
176 */
177 if (p->p_pgrp->pg_mem == 0)
178 pgdelete(p->p_pgrp);
179 /*
180 * link into new one
181 */
182 p->p_pgrp = pgrp;
183 p->p_pgrpnxt = pgrp->pg_mem;
184 pgrp->pg_mem = p;
185 }
186
187 /*
188 * remove process from process group
189 */
190 leavepgrp(p)
191 register struct proc *p;
192 {
193 register struct proc **pp = &p->p_pgrp->pg_mem;
194
195 for (; *pp; pp = &(*pp)->p_pgrpnxt)
196 if (*pp == p) {
197 *pp = p->p_pgrpnxt;
198 goto done;
199 }
200 panic("leavepgrp: can't find p in pgrp");
201 done:
202 if (!p->p_pgrp->pg_mem)
203 pgdelete(p->p_pgrp);
204 p->p_pgrp = 0;
205 }
206
207 /*
208 * delete a process group
209 */
210 pgdelete(pgrp)
211 register struct pgrp *pgrp;
212 {
213 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
214
215 if (pgrp->pg_session->s_ttyp != NULL &&
216 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
217 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
218 for (; *pgp; pgp = &(*pgp)->pg_hforw)
219 if (*pgp == pgrp) {
220 *pgp = pgrp->pg_hforw;
221 goto done;
222 }
223 panic("pgdelete: can't find pgrp on hash chain");
224 done:
225 if (--pgrp->pg_session->s_count == 0)
226 FREE(pgrp->pg_session, M_SESSION);
227 FREE(pgrp, M_PGRP);
228 }
229
230 static orphanpg();
231
232 /*
233 * Adjust pgrp jobc counters when specified process changes process group.
234 * We count the number of processes in each process group that "qualify"
235 * the group for terminal job control (those with a parent in a different
236 * process group of the same session). If that count reaches zero, the
237 * process group becomes orphaned. Check both the specified process'
238 * process group and that of its children.
239 * entering == 0 => p is leaving specified group.
240 * entering == 1 => p is entering specified group.
241 */
242 fixjobc(p, pgrp, entering)
243 register struct proc *p;
244 register struct pgrp *pgrp;
245 int entering;
246 {
247 register struct pgrp *hispgrp;
248 register struct session *mysession = pgrp->pg_session;
249
250 /*
251 * Check p's parent to see whether p qualifies its own process
252 * group; if so, adjust count for p's process group.
253 */
254 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
255 hispgrp->pg_session == mysession)
256 if (entering)
257 pgrp->pg_jobc++;
258 else if (--pgrp->pg_jobc == 0)
259 orphanpg(pgrp);
260
261 /*
262 * Check this process' children to see whether they qualify
263 * their process groups; if so, adjust counts for children's
264 * process groups.
265 */
266 for (p = p->p_cptr; p; p = p->p_osptr)
267 if ((hispgrp = p->p_pgrp) != pgrp &&
268 hispgrp->pg_session == mysession &&
269 p->p_stat != SZOMB)
270 if (entering)
271 hispgrp->pg_jobc++;
272 else if (--hispgrp->pg_jobc == 0)
273 orphanpg(hispgrp);
274 }
275
276 /*
277 * A process group has become orphaned;
278 * if there are any stopped processes in the group,
279 * hang-up all process in that group.
280 */
281 static
282 orphanpg(pg)
283 struct pgrp *pg;
284 {
285 register struct proc *p;
286
287 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
288 if (p->p_stat == SSTOP) {
289 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
290 psignal(p, SIGHUP);
291 psignal(p, SIGCONT);
292 }
293 return;
294 }
295 }
296 }
297
298 #ifdef debug
299 /* DEBUG */
300 pgrpdump()
301 {
302 register struct pgrp *pgrp;
303 register struct proc *p;
304 register i;
305
306 for (i=0; i<PIDHSZ; i++) {
307 if (pgrphash[i]) {
308 printf("\tindx %d\n", i);
309 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
310 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
311 pgrp, pgrp->pg_id, pgrp->pg_session,
312 pgrp->pg_session->s_count, pgrp->pg_mem);
313 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
314 printf("\t\tpid %d addr %x pgrp %x\n",
315 p->p_pid, p, p->p_pgrp);
316 }
317 }
318
319 }
320 }
321 }
322 #endif /* debug */
323