reorganization to move ufsmount ops to be vnode ops;
[unix-history] / usr / src / sys / kern / kern_proc.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)kern_proc.c 7.17 (Berkeley) %G%
8 */
9
10#include <sys/param.h>
11#include <sys/systm.h>
12#include <sys/map.h>
13#include <sys/kernel.h>
14#include <sys/proc.h>
15#include <sys/buf.h>
16#include <sys/seg.h>
17#include <sys/acct.h>
18#include <sys/wait.h>
19#include <sys/file.h>
20#include <ufs/ufs/quota.h>
21#include <sys/uio.h>
22#include <sys/malloc.h>
23#include <sys/mbuf.h>
24#include <sys/ioctl.h>
25#include <sys/tty.h>
26
27/*
28 * Is p an inferior of the current process?
29 */
30inferior(p)
31 register struct proc *p;
32{
33
34 for (; p != curproc; p = p->p_pptr)
35 if (p->p_pid == 0)
36 return (0);
37 return (1);
38}
39
40/*
41 * Locate a process by number
42 */
43struct proc *
44pfind(pid)
45 register pid;
46{
47 register struct proc *p = pidhash[PIDHASH(pid)];
48
49 for (; p; p = p->p_hash)
50 if (p->p_pid == pid)
51 return (p);
52 return ((struct proc *)0);
53}
54
55/*
56 * Locate a process group by number
57 */
58struct pgrp *
59pgfind(pgid)
60 register pid_t pgid;
61{
62 register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
63
64 for (; pgrp; pgrp = pgrp->pg_hforw)
65 if (pgrp->pg_id == pgid)
66 return (pgrp);
67 return ((struct pgrp *)0);
68}
69
70/*
71 * Move p to a new or existing process group (and session)
72 */
73enterpgrp(p, pgid, mksess)
74 register struct proc *p;
75 pid_t pgid;
76{
77 register struct pgrp *pgrp = pgfind(pgid);
78 register struct proc **pp;
79 register struct proc *cp;
80 int n;
81
82#ifdef DIAGNOSTIC
83 if (pgrp && mksess) /* firewalls */
84 panic("enterpgrp: setsid into non-empty pgrp");
85 if (SESS_LEADER(p))
86 panic("enterpgrp: session leader attempted setpgrp");
87#endif
88 if (pgrp == NULL) {
89 /*
90 * new process group
91 */
92#ifdef DIAGNOSTIC
93 if (p->p_pid != pgid)
94 panic("enterpgrp: new pgrp and pid != pgid");
95#endif
96 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
97 M_WAITOK);
98 if (mksess) {
99 register struct session *sess;
100
101 /*
102 * new session
103 */
104 MALLOC(sess, struct session *, sizeof(struct session),
105 M_SESSION, M_WAITOK);
106 sess->s_leader = p;
107 sess->s_count = 1;
108 sess->s_ttyvp = NULL;
109 sess->s_ttyp = NULL;
110 bcopy(p->p_session->s_login, sess->s_login,
111 sizeof(sess->s_login));
112 p->p_flag &= ~SCTTY;
113 pgrp->pg_session = sess;
114#ifdef DIAGNOSTIC
115 if (p != curproc)
116 panic("enterpgrp: mksession and p != curproc");
117#endif
118 } else {
119 pgrp->pg_session = p->p_session;
120 pgrp->pg_session->s_count++;
121 }
122 pgrp->pg_id = pgid;
123 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
124 pgrphash[n] = pgrp;
125 pgrp->pg_jobc = 0;
126 pgrp->pg_mem = NULL;
127 } else if (pgrp == p->p_pgrp)
128 return;
129
130 /*
131 * Adjust eligibility of affected pgrps to participate in job control.
132 * Increment eligibility counts before decrementing, otherwise we
133 * could reach 0 spuriously during the first call.
134 */
135 fixjobc(p, pgrp, 1);
136 fixjobc(p, p->p_pgrp, 0);
137
138 /*
139 * unlink p from old process group
140 */
141 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt)
142 if (*pp == p) {
143 *pp = p->p_pgrpnxt;
144 goto done;
145 }
146 panic("enterpgrp: can't find p on old pgrp");
147done:
148 /*
149 * delete old if empty
150 */
151 if (p->p_pgrp->pg_mem == 0)
152 pgdelete(p->p_pgrp);
153 /*
154 * link into new one
155 */
156 p->p_pgrp = pgrp;
157 p->p_pgrpnxt = pgrp->pg_mem;
158 pgrp->pg_mem = p;
159}
160
161/*
162 * remove process from process group
163 */
164leavepgrp(p)
165 register struct proc *p;
166{
167 register struct proc **pp = &p->p_pgrp->pg_mem;
168
169 for (; *pp; pp = &(*pp)->p_pgrpnxt)
170 if (*pp == p) {
171 *pp = p->p_pgrpnxt;
172 goto done;
173 }
174 panic("leavepgrp: can't find p in pgrp");
175done:
176 if (!p->p_pgrp->pg_mem)
177 pgdelete(p->p_pgrp);
178 p->p_pgrp = 0;
179}
180
181/*
182 * delete a process group
183 */
184pgdelete(pgrp)
185 register struct pgrp *pgrp;
186{
187 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
188
189 if (pgrp->pg_session->s_ttyp != NULL &&
190 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
191 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
192 for (; *pgp; pgp = &(*pgp)->pg_hforw)
193 if (*pgp == pgrp) {
194 *pgp = pgrp->pg_hforw;
195 goto done;
196 }
197 panic("pgdelete: can't find pgrp on hash chain");
198done:
199 if (--pgrp->pg_session->s_count == 0)
200 FREE(pgrp->pg_session, M_SESSION);
201 FREE(pgrp, M_PGRP);
202}
203
204static orphanpg();
205
206/*
207 * Adjust pgrp jobc counters when specified process changes process group.
208 * We count the number of processes in each process group that "qualify"
209 * the group for terminal job control (those with a parent in a different
210 * process group of the same session). If that count reaches zero, the
211 * process group becomes orphaned. Check both the specified process'
212 * process group and that of its children.
213 * entering == 0 => p is leaving specified group.
214 * entering == 1 => p is entering specified group.
215 */
216fixjobc(p, pgrp, entering)
217 register struct proc *p;
218 register struct pgrp *pgrp;
219 int entering;
220{
221 register struct pgrp *hispgrp;
222 register struct session *mysession = pgrp->pg_session;
223
224 /*
225 * Check p's parent to see whether p qualifies its own process
226 * group; if so, adjust count for p's process group.
227 */
228 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
229 hispgrp->pg_session == mysession)
230 if (entering)
231 pgrp->pg_jobc++;
232 else if (--pgrp->pg_jobc == 0)
233 orphanpg(pgrp);
234
235 /*
236 * Check this process' children to see whether they qualify
237 * their process groups; if so, adjust counts for children's
238 * process groups.
239 */
240 for (p = p->p_cptr; p; p = p->p_osptr)
241 if ((hispgrp = p->p_pgrp) != pgrp &&
242 hispgrp->pg_session == mysession &&
243 p->p_stat != SZOMB)
244 if (entering)
245 hispgrp->pg_jobc++;
246 else if (--hispgrp->pg_jobc == 0)
247 orphanpg(hispgrp);
248}
249
250/*
251 * A process group has become orphaned;
252 * if there are any stopped processes in the group,
253 * hang-up all process in that group.
254 */
255static
256orphanpg(pg)
257 struct pgrp *pg;
258{
259 register struct proc *p;
260
261 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
262 if (p->p_stat == SSTOP) {
263 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
264 psignal(p, SIGHUP);
265 psignal(p, SIGCONT);
266 }
267 return;
268 }
269 }
270}
271
272#ifdef debug
273/* DEBUG */
274pgrpdump()
275{
276 register struct pgrp *pgrp;
277 register struct proc *p;
278 register i;
279
280 for (i=0; i<PIDHSZ; i++) {
281 if (pgrphash[i]) {
282 printf("\tindx %d\n", i);
283 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
284 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
285 pgrp, pgrp->pg_id, pgrp->pg_session,
286 pgrp->pg_session->s_count, pgrp->pg_mem);
287 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
288 printf("\t\tpid %d addr %x pgrp %x\n",
289 p->p_pid, p, p->p_pgrp);
290 }
291 }
292
293 }
294 }
295}
296#endif /* debug */