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