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