Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
3fb7685a | 2 | * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. |
c4ec2128 | 3 | * All rights reserved. |
da7c5cc6 | 4 | * |
dbf0c423 | 5 | * %sccs.include.redist.c% |
c4ec2128 | 6 | * |
f3aac35d | 7 | * @(#)kern_proc.c 7.16 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
961945a8 | 9 | |
94368568 JB |
10 | #include "param.h" |
11 | #include "systm.h" | |
12 | #include "map.h" | |
94368568 JB |
13 | #include "kernel.h" |
14 | #include "proc.h" | |
15 | #include "buf.h" | |
94368568 JB |
16 | #include "seg.h" |
17 | #include "acct.h" | |
18 | #include "wait.h" | |
94368568 | 19 | #include "file.h" |
c4ec2128 | 20 | #include "../ufs/quota.h" |
94368568 | 21 | #include "uio.h" |
8fe87cbb | 22 | #include "malloc.h" |
94368568 | 23 | #include "mbuf.h" |
5b6ff773 | 24 | #include "ioctl.h" |
8fe87cbb | 25 | #include "tty.h" |
a1bce776 | 26 | |
29dd101b | 27 | /* |
4147b3f6 | 28 | * Is p an inferior of the current process? |
29dd101b | 29 | */ |
4147b3f6 | 30 | inferior(p) |
a2a2a0d6 | 31 | register struct proc *p; |
29dd101b | 32 | { |
2dccc728 | 33 | |
bed84066 MK |
34 | for (; p != curproc; p = p->p_pptr) |
35 | if (p->p_pid == 0) | |
4147b3f6 BJ |
36 | return (0); |
37 | return (1); | |
29dd101b | 38 | } |
a2a2a0d6 | 39 | |
b3ce9b0f MK |
40 | /* |
41 | * Locate a process by number | |
42 | */ | |
a2a2a0d6 BJ |
43 | struct proc * |
44 | pfind(pid) | |
8fe87cbb | 45 | register pid; |
a2a2a0d6 | 46 | { |
b3ce9b0f | 47 | register struct proc *p = pidhash[PIDHASH(pid)]; |
a2a2a0d6 | 48 | |
b3ce9b0f | 49 | for (; p; p = p->p_hash) |
a2a2a0d6 BJ |
50 | if (p->p_pid == pid) |
51 | return (p); | |
52 | return ((struct proc *)0); | |
53 | } | |
1d348849 | 54 | |
8fe87cbb MT |
55 | /* |
56 | * Locate a process group by number | |
57 | */ | |
58 | struct pgrp * | |
59 | pgfind(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) | |
b3ce9b0f | 66 | return (pgrp); |
8fe87cbb MT |
67 | return ((struct pgrp *)0); |
68 | } | |
69 | ||
70 | /* | |
71 | * Move p to a new or existing process group (and session) | |
72 | */ | |
bed84066 | 73 | enterpgrp(p, pgid, mksess) |
8fe87cbb MT |
74 | register struct proc *p; |
75 | pid_t pgid; | |
76 | { | |
77 | register struct pgrp *pgrp = pgfind(pgid); | |
2dccc728 | 78 | register struct proc **pp; |
8fe87cbb | 79 | register struct proc *cp; |
2dccc728 | 80 | int n; |
8fe87cbb | 81 | |
944e89dc | 82 | #ifdef DIAGNOSTIC |
8fe87cbb | 83 | if (pgrp && mksess) /* firewalls */ |
bed84066 | 84 | panic("enterpgrp: setsid into non-empty pgrp"); |
8fe87cbb | 85 | if (SESS_LEADER(p)) |
bed84066 | 86 | panic("enterpgrp: session leader attempted setpgrp"); |
944e89dc | 87 | #endif |
2e8f8cae | 88 | if (pgrp == NULL) { |
8fe87cbb MT |
89 | /* |
90 | * new process group | |
91 | */ | |
944e89dc | 92 | #ifdef DIAGNOSTIC |
8fe87cbb | 93 | if (p->p_pid != pgid) |
bed84066 | 94 | panic("enterpgrp: new pgrp and pid != pgid"); |
944e89dc | 95 | #endif |
8fe87cbb MT |
96 | MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, |
97 | M_WAITOK); | |
98 | if (mksess) { | |
99 | register struct session *sess; | |
f3aac35d | 100 | |
8fe87cbb MT |
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; | |
944e89dc MT |
108 | sess->s_ttyvp = NULL; |
109 | sess->s_ttyp = NULL; | |
f3aac35d MK |
110 | bcopy(p->p_session->s_login, sess->s_login, |
111 | sizeof(sess->s_login)); | |
944e89dc | 112 | p->p_flag &= ~SCTTY; |
8fe87cbb | 113 | pgrp->pg_session = sess; |
944e89dc | 114 | #ifdef DIAGNOSTIC |
bed84066 MK |
115 | if (p != curproc) |
116 | panic("enterpgrp: mksession and p != curproc"); | |
944e89dc | 117 | #endif |
8fe87cbb MT |
118 | } else { |
119 | pgrp->pg_session = p->p_session; | |
120 | pgrp->pg_session->s_count++; | |
121 | } | |
122 | pgrp->pg_id = pgid; | |
2dccc728 | 123 | pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; |
8fe87cbb MT |
124 | pgrphash[n] = pgrp; |
125 | pgrp->pg_jobc = 0; | |
944e89dc | 126 | pgrp->pg_mem = NULL; |
69ed180a MT |
127 | } else if (pgrp == p->p_pgrp) |
128 | return; | |
2dccc728 | 129 | |
8fe87cbb | 130 | /* |
2dccc728 MK |
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. | |
8fe87cbb | 134 | */ |
2dccc728 MK |
135 | fixjobc(p, pgrp, 1); |
136 | fixjobc(p, p->p_pgrp, 0); | |
137 | ||
8fe87cbb MT |
138 | /* |
139 | * unlink p from old process group | |
140 | */ | |
2dccc728 | 141 | for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) |
8fe87cbb MT |
142 | if (*pp == p) { |
143 | *pp = p->p_pgrpnxt; | |
144 | goto done; | |
145 | } | |
bed84066 | 146 | panic("enterpgrp: can't find p on old pgrp"); |
8fe87cbb | 147 | done: |
2dccc728 MK |
148 | /* |
149 | * delete old if empty | |
150 | */ | |
151 | if (p->p_pgrp->pg_mem == 0) | |
152 | pgdelete(p->p_pgrp); | |
8fe87cbb MT |
153 | /* |
154 | * link into new one | |
155 | */ | |
2dccc728 | 156 | p->p_pgrp = pgrp; |
8fe87cbb MT |
157 | p->p_pgrpnxt = pgrp->pg_mem; |
158 | pgrp->pg_mem = p; | |
8fe87cbb MT |
159 | } |
160 | ||
161 | /* | |
162 | * remove process from process group | |
163 | */ | |
bed84066 | 164 | leavepgrp(p) |
8fe87cbb MT |
165 | register struct proc *p; |
166 | { | |
167 | register struct proc **pp = &p->p_pgrp->pg_mem; | |
8fe87cbb MT |
168 | |
169 | for (; *pp; pp = &(*pp)->p_pgrpnxt) | |
170 | if (*pp == p) { | |
171 | *pp = p->p_pgrpnxt; | |
172 | goto done; | |
173 | } | |
bed84066 | 174 | panic("leavepgrp: can't find p in pgrp"); |
8fe87cbb MT |
175 | done: |
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 | */ | |
184 | pgdelete(pgrp) | |
185 | register struct pgrp *pgrp; | |
186 | { | |
187 | register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; | |
188 | ||
944e89dc MT |
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; | |
8fe87cbb MT |
192 | for (; *pgp; pgp = &(*pgp)->pg_hforw) |
193 | if (*pgp == pgrp) { | |
194 | *pgp = pgrp->pg_hforw; | |
195 | goto done; | |
196 | } | |
2e8f8cae | 197 | panic("pgdelete: can't find pgrp on hash chain"); |
8fe87cbb MT |
198 | done: |
199 | if (--pgrp->pg_session->s_count == 0) | |
200 | FREE(pgrp->pg_session, M_SESSION); | |
201 | FREE(pgrp, M_PGRP); | |
202 | } | |
203 | ||
3fb7685a MK |
204 | static orphanpg(); |
205 | ||
69ed180a | 206 | /* |
2dccc728 MK |
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. | |
69ed180a | 215 | */ |
2dccc728 | 216 | fixjobc(p, pgrp, entering) |
69ed180a | 217 | register struct proc *p; |
2dccc728 MK |
218 | register struct pgrp *pgrp; |
219 | int entering; | |
69ed180a | 220 | { |
2dccc728 MK |
221 | register struct pgrp *hispgrp; |
222 | register struct session *mysession = pgrp->pg_session; | |
69ed180a | 223 | |
2dccc728 MK |
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 && | |
69ed180a | 229 | hispgrp->pg_session == mysession) |
2dccc728 MK |
230 | if (entering) |
231 | pgrp->pg_jobc++; | |
232 | else if (--pgrp->pg_jobc == 0) | |
233 | orphanpg(pgrp); | |
69ed180a | 234 | |
2dccc728 MK |
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 && | |
69ed180a MT |
242 | hispgrp->pg_session == mysession && |
243 | p->p_stat != SZOMB) | |
2dccc728 | 244 | if (entering) |
69ed180a | 245 | hispgrp->pg_jobc++; |
2dccc728 MK |
246 | else if (--hispgrp->pg_jobc == 0) |
247 | orphanpg(hispgrp); | |
248 | } | |
69ed180a | 249 | |
2dccc728 MK |
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 | */ | |
255 | static | |
256 | orphanpg(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); | |
69ed180a | 266 | } |
2dccc728 MK |
267 | return; |
268 | } | |
269 | } | |
69ed180a | 270 | } |
2dccc728 | 271 | |
c4ec2128 | 272 | #ifdef debug |
8fe87cbb MT |
273 | /* DEBUG */ |
274 | pgrpdump() | |
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 | } | |
c4ec2128 | 296 | #endif /* debug */ |