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