|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1989, 1991, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95
59: */
60:
61: #include <sys/param.h>
62: #include <sys/systm.h>
63: #include <sys/kernel.h>
64: #include <sys/proc.h>
65: #include <sys/buf.h>
66: #include <sys/acct.h>
67: #include <sys/wait.h>
68: #include <sys/file.h>
69: #include <ufs/ufs/quota.h>
70: #include <sys/uio.h>
71: #include <sys/malloc.h>
72: #include <sys/mbuf.h>
73: #include <sys/ioctl.h>
74: #include <sys/tty.h>
75: #include <sys/signalvar.h>
76:
77: /*
78: * Structure associated with user cacheing.
79: */
80: struct uidinfo {
81: LIST_ENTRY(uidinfo) ui_hash;
82: uid_t ui_uid;
83: long ui_proccnt;
84: };
85: #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
86: LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
87: u_long uihash; /* size of hash table - 1 */
88:
89: /*
90: * Other process lists
91: */
92: struct pidhashhead *pidhashtbl;
93: u_long pidhash;
94: struct pgrphashhead *pgrphashtbl;
95: u_long pgrphash;
96: struct proclist allproc;
97: struct proclist zombproc;
98:
99: /*
100: * Initialize global process hashing structures.
101: */
102: void
103: procinit()
104: {
105:
106: LIST_INIT(&allproc);
107: LIST_INIT(&zombproc);
108: pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
109: pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
110: uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
111: }
112:
113: /*
114: * Change the count associated with number of processes
115: * a given user is using.
116: */
117: int
118: chgproccnt(uid, diff)
119: uid_t uid;
120: int diff;
121: {
122: register struct uidinfo *uip;
123: register struct uihashhead *uipp;
124:
125: uipp = UIHASH(uid);
126: for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
127: if (uip->ui_uid == uid)
128: break;
129: if (uip) {
130: uip->ui_proccnt += diff;
131: if (uip->ui_proccnt > 0)
132: return (uip->ui_proccnt);
133: if (uip->ui_proccnt < 0)
134: panic("chgproccnt: procs < 0");
135: LIST_REMOVE(uip, ui_hash);
136: FREE_ZONE(uip, sizeof *uip, M_PROC);
137: return (0);
138: }
139: if (diff <= 0) {
140: if (diff == 0)
141: return(0);
142: panic("chgproccnt: lost user");
143: }
144: MALLOC_ZONE(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
145: LIST_INSERT_HEAD(uipp, uip, ui_hash);
146: uip->ui_uid = uid;
147: uip->ui_proccnt = diff;
148: return (diff);
149: }
150:
151: /*
152: * Is p an inferior of the current process?
153: */
154: int
155: inferior(p)
156: register struct proc *p;
157: {
158:
159: for (; p != current_proc(); p = p->p_pptr)
160: if (p->p_pid == 0)
161: return (0);
162: return (1);
163: }
164:
165: /*
166: * Locate a process by number
167: */
168: struct proc *
169: pfind(pid)
170: register pid_t pid;
171: {
172: register struct proc *p;
173:
174: if (!pid)
175: return (kernproc);
176:
177: for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next)
178: if (p->p_pid == pid)
179: return (p);
180: return (NULL);
181: }
182:
183: /*
184: * Locate a process group by number
185: */
186: struct pgrp *
187: pgfind(pgid)
188: register pid_t pgid;
189: {
190: register struct pgrp *pgrp;
191:
192: for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next)
193: if (pgrp->pg_id == pgid)
194: return (pgrp);
195: return (NULL);
196: }
197:
198:
199: /*
200: * Move p to a new or existing process group (and session)
201: */
202: int
203: enterpgrp(p, pgid, mksess)
204: register struct proc *p;
205: pid_t pgid;
206: int mksess;
207: {
208: register struct pgrp *pgrp = pgfind(pgid);
209:
210: #if DIAGNOSTIC
211: if (pgrp != NULL && mksess) /* firewalls */
212: panic("enterpgrp: setsid into non-empty pgrp");
213: if (SESS_LEADER(p))
214: panic("enterpgrp: session leader attempted setpgrp");
215: #endif
216: if (pgrp == NULL) {
217: pid_t savepid = p->p_pid;
218: struct proc *np;
219: /*
220: * new process group
221: */
222: #if DIAGNOSTIC
223: if (p->p_pid != pgid)
224: panic("enterpgrp: new pgrp and pid != pgid");
225: #endif
226: MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
227: M_WAITOK);
228: if ((np = pfind(savepid)) == NULL || np != p)
229: return (ESRCH);
230: if (mksess) {
231: register struct session *sess;
232:
233: /*
234: * new session
235: */
236: MALLOC_ZONE(sess, struct session *,
237: sizeof(struct session), M_SESSION, M_WAITOK);
238: sess->s_leader = p;
239: sess->s_count = 1;
240: sess->s_ttyvp = NULL;
241: sess->s_ttyp = NULL;
242: bcopy(p->p_session->s_login, sess->s_login,
243: sizeof(sess->s_login));
244: p->p_flag &= ~P_CONTROLT;
245: pgrp->pg_session = sess;
246: #if DIAGNOSTIC
247: if (p != current_proc())
248: panic("enterpgrp: mksession and p != curproc");
249: #endif
250: } else {
251: pgrp->pg_session = p->p_session;
252: pgrp->pg_session->s_count++;
253: }
254: pgrp->pg_id = pgid;
255: LIST_INIT(&pgrp->pg_members);
256: LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
257: pgrp->pg_jobc = 0;
258: } else if (pgrp == p->p_pgrp)
259: return (0);
260:
261: /*
262: * Adjust eligibility of affected pgrps to participate in job control.
263: * Increment eligibility counts before decrementing, otherwise we
264: * could reach 0 spuriously during the first call.
265: */
266: fixjobc(p, pgrp, 1);
267: fixjobc(p, p->p_pgrp, 0);
268:
269: LIST_REMOVE(p, p_pglist);
270: if (p->p_pgrp->pg_members.lh_first == 0)
271: pgdelete(p->p_pgrp);
272: p->p_pgrp = pgrp;
273: LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
274: return (0);
275: }
276:
277: /*
278: * remove process from process group
279: */
280: int
281: leavepgrp(p)
282: register struct proc *p;
283: {
284:
285: LIST_REMOVE(p, p_pglist);
286: if (p->p_pgrp->pg_members.lh_first == 0)
287: pgdelete(p->p_pgrp);
288: p->p_pgrp = 0;
289: return (0);
290: }
291:
292: /*
293: * delete a process group
294: */
295: void
296: pgdelete(pgrp)
297: register struct pgrp *pgrp;
298: {
299:
300: if (pgrp->pg_session->s_ttyp != NULL &&
301: pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
302: pgrp->pg_session->s_ttyp->t_pgrp = NULL;
303: LIST_REMOVE(pgrp, pg_hash);
304: if (--pgrp->pg_session->s_count == 0)
305: FREE_ZONE(pgrp->pg_session, sizeof(struct session), M_SESSION);
306: FREE_ZONE(pgrp, sizeof *pgrp, M_PGRP);
307: }
308:
309: void
310: sessrele(sess)
311: struct session *sess;
312: {
313: if (--sess->s_count == 0)
314: FREE_ZONE(sess, sizeof (struct session), M_SESSION);
315: }
316:
317: static void orphanpg();
318:
319: /*
320: * Adjust pgrp jobc counters when specified process changes process group.
321: * We count the number of processes in each process group that "qualify"
322: * the group for terminal job control (those with a parent in a different
323: * process group of the same session). If that count reaches zero, the
324: * process group becomes orphaned. Check both the specified process'
325: * process group and that of its children.
326: * entering == 0 => p is leaving specified group.
327: * entering == 1 => p is entering specified group.
328: */
329: void
330: fixjobc(p, pgrp, entering)
331: register struct proc *p;
332: register struct pgrp *pgrp;
333: int entering;
334: {
335: register struct pgrp *hispgrp;
336: register struct session *mysession = pgrp->pg_session;
337:
338: /*
339: * Check p's parent to see whether p qualifies its own process
340: * group; if so, adjust count for p's process group.
341: */
342: if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
343: hispgrp->pg_session == mysession)
344: if (entering)
345: pgrp->pg_jobc++;
346: else if (--pgrp->pg_jobc == 0)
347: orphanpg(pgrp);
348:
349: /*
350: * Check this process' children to see whether they qualify
351: * their process groups; if so, adjust counts for children's
352: * process groups.
353: */
354: for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next)
355: if ((hispgrp = p->p_pgrp) != pgrp &&
356: hispgrp->pg_session == mysession &&
357: p->p_stat != SZOMB)
358: if (entering)
359: hispgrp->pg_jobc++;
360: else if (--hispgrp->pg_jobc == 0)
361: orphanpg(hispgrp);
362: }
363:
364: /*
365: * A process group has become orphaned;
366: * if there are any stopped processes in the group,
367: * hang-up all process in that group.
368: */
369: static void
370: orphanpg(pg)
371: struct pgrp *pg;
372: {
373: register struct proc *p;
374:
375: for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
376: if (p->p_stat == SSTOP) {
377: for (p = pg->pg_members.lh_first; p != 0;
378: p = p->p_pglist.le_next) {
379: psignal(p, SIGHUP);
380: psignal(p, SIGCONT);
381: }
382: return;
383: }
384: }
385: }
386:
387: #ifdef DEBUG
388: void
389: pgrpdump()
390: {
391: register struct pgrp *pgrp;
392: register struct proc *p;
393: register i;
394:
395: for (i = 0; i <= pgrphash; i++) {
396: if (pgrp = pgrphashtbl[i].lh_first) {
397: printf("\tindx %d\n", i);
398: for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) {
399: printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n",
400: pgrp, pgrp->pg_id, pgrp->pg_session,
401: pgrp->pg_session->s_count,
402: pgrp->pg_members.lh_first);
403: for (p = pgrp->pg_members.lh_first; p != 0;
404: p = p->p_pglist.le_next) {
405: printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",
406: p->p_pid, p, p->p_pgrp);
407: }
408: }
409: }
410: }
411: }
412: #endif /* DEBUG */
413:
414: struct proc * current_proc_EXTERNAL()
415: {
416: return (current_proc());
417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.