kern_proc.c revision 1.7 1 /*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. 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 8.4 (Berkeley) 1/4/94
34 * $Id: kern_proc.c,v 1.7 1994/05/19 05:57:50 cgd Exp $
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/map.h>
40 #include <sys/kernel.h>
41 #include <sys/proc.h>
42 #include <sys/buf.h>
43 #include <sys/acct.h>
44 #include <sys/wait.h>
45 #include <sys/file.h>
46 #include <ufs/quota.h> /* XXX */
47 #include <sys/uio.h>
48 #include <sys/malloc.h>
49 #include <sys/mbuf.h>
50 #include <sys/ioctl.h>
51 #include <sys/tty.h>
52
53 /*
54 * Structure associated with user cacheing.
55 */
56 struct uidinfo {
57 struct uidinfo *ui_next;
58 struct uidinfo **ui_prev;
59 uid_t ui_uid;
60 long ui_proccnt;
61 } **uihashtbl;
62 u_long uihash; /* size of hash table - 1 */
63 #define UIHASH(uid) ((uid) & uihash)
64
65 /*
66 * Allocate a hash table.
67 */
68 usrinfoinit()
69 {
70
71 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
72 }
73
74 /*
75 * Change the count associated with number of processes
76 * a given user is using.
77 */
78 int
79 chgproccnt(uid, diff)
80 uid_t uid;
81 int diff;
82 {
83 register struct uidinfo **uipp, *uip, *uiq;
84
85 uipp = &uihashtbl[UIHASH(uid)];
86 for (uip = *uipp; uip; uip = uip->ui_next)
87 if (uip->ui_uid == uid)
88 break;
89 if (uip) {
90 uip->ui_proccnt += diff;
91 if (uip->ui_proccnt > 0)
92 return (uip->ui_proccnt);
93 if (uip->ui_proccnt < 0)
94 panic("chgproccnt: procs < 0");
95 if (uiq = uip->ui_next)
96 uiq->ui_prev = uip->ui_prev;
97 *uip->ui_prev = uiq;
98 FREE(uip, M_PROC);
99 return (0);
100 }
101 if (diff <= 0) {
102 if (diff == 0)
103 return(0);
104 panic("chgproccnt: lost user");
105 }
106 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
107 if (uiq = *uipp)
108 uiq->ui_prev = &uip->ui_next;
109 uip->ui_next = uiq;
110 uip->ui_prev = uipp;
111 *uipp = uip;
112 uip->ui_uid = uid;
113 uip->ui_proccnt = diff;
114 return (diff);
115 }
116
117 /*
118 * Is p an inferior of the current process?
119 */
120 inferior(p)
121 register struct proc *p;
122 {
123
124 for (; p != curproc; p = p->p_pptr)
125 if (p->p_pid == 0)
126 return (0);
127 return (1);
128 }
129
130 /*
131 * Locate a process by number
132 */
133 struct proc *
134 pfind(pid)
135 register pid_t pid;
136 {
137 register struct proc *p;
138
139 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash)
140 if (p->p_pid == pid)
141 return (p);
142 return (NULL);
143 }
144
145 /*
146 * Locate a process group by number
147 */
148 struct pgrp *
149 pgfind(pgid)
150 register pid_t pgid;
151 {
152 register struct pgrp *pgrp;
153
154 for (pgrp = pgrphash[PIDHASH(pgid)];
155 pgrp != NULL; pgrp = pgrp->pg_hforw)
156 if (pgrp->pg_id == pgid)
157 return (pgrp);
158 return (NULL);
159 }
160
161 /*
162 * Move p to a new or existing process group (and session)
163 */
164 enterpgrp(p, pgid, mksess)
165 register struct proc *p;
166 pid_t pgid;
167 int mksess;
168 {
169 register struct pgrp *pgrp = pgfind(pgid);
170 register struct proc **pp;
171 int n;
172
173 #ifdef DIAGNOSTIC
174 if (pgrp != NULL && mksess) /* firewalls */
175 panic("enterpgrp: setsid into non-empty pgrp");
176 if (SESS_LEADER(p))
177 panic("enterpgrp: session leader attempted setpgrp");
178 #endif
179 if (pgrp == NULL) {
180 pid_t savepid = p->p_pid;
181 struct proc *np;
182 /*
183 * new process group
184 */
185 #ifdef DIAGNOSTIC
186 if (p->p_pid != pgid)
187 panic("enterpgrp: new pgrp and pid != pgid");
188 #endif
189 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
190 M_WAITOK);
191 if ((np = pfind(savepid)) == NULL || np != p)
192 return (ESRCH);
193 if (mksess) {
194 register struct session *sess;
195
196 /*
197 * new session
198 */
199 MALLOC(sess, struct session *, sizeof(struct session),
200 M_SESSION, M_WAITOK);
201 sess->s_leader = p;
202 sess->s_count = 1;
203 sess->s_ttyvp = NULL;
204 sess->s_ttyp = NULL;
205 bcopy(p->p_session->s_login, sess->s_login,
206 sizeof(sess->s_login));
207 p->p_flag &= ~P_CONTROLT;
208 pgrp->pg_session = sess;
209 #ifdef DIAGNOSTIC
210 if (p != curproc)
211 panic("enterpgrp: mksession and p != curproc");
212 #endif
213 } else {
214 pgrp->pg_session = p->p_session;
215 pgrp->pg_session->s_count++;
216 }
217 pgrp->pg_id = pgid;
218 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
219 pgrphash[n] = pgrp;
220 pgrp->pg_jobc = 0;
221 pgrp->pg_mem = NULL;
222 } else if (pgrp == p->p_pgrp)
223 return (0);
224
225 /*
226 * Adjust eligibility of affected pgrps to participate in job control.
227 * Increment eligibility counts before decrementing, otherwise we
228 * could reach 0 spuriously during the first call.
229 */
230 fixjobc(p, pgrp, 1);
231 fixjobc(p, p->p_pgrp, 0);
232
233 /*
234 * unlink p from old process group
235 */
236 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) {
237 if (*pp == p) {
238 *pp = p->p_pgrpnxt;
239 break;
240 }
241 }
242 #ifdef DIAGNOSTIC
243 if (pp == NULL)
244 panic("enterpgrp: can't find p on old pgrp");
245 #endif
246 /*
247 * delete old if empty
248 */
249 if (p->p_pgrp->pg_mem == 0)
250 pgdelete(p->p_pgrp);
251 /*
252 * link into new one
253 */
254 p->p_pgrp = pgrp;
255 p->p_pgrpnxt = pgrp->pg_mem;
256 pgrp->pg_mem = p;
257 return (0);
258 }
259
260 /*
261 * remove process from process group
262 */
263 leavepgrp(p)
264 register struct proc *p;
265 {
266 register struct proc **pp = &p->p_pgrp->pg_mem;
267
268 for (; *pp; pp = &(*pp)->p_pgrpnxt) {
269 if (*pp == p) {
270 *pp = p->p_pgrpnxt;
271 break;
272 }
273 }
274 #ifdef DIAGNOSTIC
275 if (pp == NULL)
276 panic("leavepgrp: can't find p in pgrp");
277 #endif
278 if (!p->p_pgrp->pg_mem)
279 pgdelete(p->p_pgrp);
280 p->p_pgrp = 0;
281 return (0);
282 }
283
284 /*
285 * delete a process group
286 */
287 pgdelete(pgrp)
288 register struct pgrp *pgrp;
289 {
290 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
291
292 if (pgrp->pg_session->s_ttyp != NULL &&
293 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
294 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
295 for (; *pgp; pgp = &(*pgp)->pg_hforw) {
296 if (*pgp == pgrp) {
297 *pgp = pgrp->pg_hforw;
298 break;
299 }
300 }
301 #ifdef DIAGNOSTIC
302 if (pgp == NULL)
303 panic("pgdelete: can't find pgrp on hash chain");
304 #endif
305 if (--pgrp->pg_session->s_count == 0)
306 FREE(pgrp->pg_session, M_SESSION);
307 FREE(pgrp, M_PGRP);
308 }
309
310 static void orphanpg();
311
312 /*
313 * Adjust pgrp jobc counters when specified process changes process group.
314 * We count the number of processes in each process group that "qualify"
315 * the group for terminal job control (those with a parent in a different
316 * process group of the same session). If that count reaches zero, the
317 * process group becomes orphaned. Check both the specified process'
318 * process group and that of its children.
319 * entering == 0 => p is leaving specified group.
320 * entering == 1 => p is entering specified group.
321 */
322 void
323 fixjobc(p, pgrp, entering)
324 register struct proc *p;
325 register struct pgrp *pgrp;
326 int entering;
327 {
328 register struct pgrp *hispgrp;
329 register struct session *mysession = pgrp->pg_session;
330
331 /*
332 * Check p's parent to see whether p qualifies its own process
333 * group; if so, adjust count for p's process group.
334 */
335 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
336 hispgrp->pg_session == mysession)
337 if (entering)
338 pgrp->pg_jobc++;
339 else if (--pgrp->pg_jobc == 0)
340 orphanpg(pgrp);
341
342 /*
343 * Check this process' children to see whether they qualify
344 * their process groups; if so, adjust counts for children's
345 * process groups.
346 */
347 for (p = p->p_cptr; p; p = p->p_osptr)
348 if ((hispgrp = p->p_pgrp) != pgrp &&
349 hispgrp->pg_session == mysession &&
350 p->p_stat != SZOMB)
351 if (entering)
352 hispgrp->pg_jobc++;
353 else if (--hispgrp->pg_jobc == 0)
354 orphanpg(hispgrp);
355 }
356
357 /*
358 * A process group has become orphaned;
359 * if there are any stopped processes in the group,
360 * hang-up all process in that group.
361 */
362 static void
363 orphanpg(pg)
364 struct pgrp *pg;
365 {
366 register struct proc *p;
367
368 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
369 if (p->p_stat == SSTOP) {
370 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
371 psignal(p, SIGHUP);
372 psignal(p, SIGCONT);
373 }
374 return;
375 }
376 }
377 }
378
379 #ifdef debug
380 /* DEBUG */
381 pgrpdump()
382 {
383 register struct pgrp *pgrp;
384 register struct proc *p;
385 register i;
386
387 for (i=0; i<PIDHSZ; i++) {
388 if (pgrphash[i]) {
389 printf("\tindx %d\n", i);
390 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
391 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
392 pgrp, pgrp->pg_id, pgrp->pg_session,
393 pgrp->pg_session->s_count, pgrp->pg_mem);
394 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
395 printf("\t\tpid %d addr %x pgrp %x\n",
396 p->p_pid, p, p->p_pgrp);
397 }
398 }
399
400 }
401 }
402 }
403 #endif /* debug */
404