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