have to protect acct_process from acctwatch closing the vnode
[unix-history] / usr / src / sys / kern / kern_proc.c
CommitLineData
da7c5cc6 1/*
c34daa85
KB
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
dbf0c423 5 * %sccs.include.redist.c%
c4ec2128 6 *
3ef0a118 7 * @(#)kern_proc.c 8.5 (Berkeley) %G%
da7c5cc6 8 */
961945a8 9
4f6e87b7
KB
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>
4f6e87b7
KB
16#include <sys/acct.h>
17#include <sys/wait.h>
18#include <sys/file.h>
19#include <ufs/ufs/quota.h>
20#include <sys/uio.h>
21#include <sys/malloc.h>
22#include <sys/mbuf.h>
23#include <sys/ioctl.h>
24#include <sys/tty.h>
a1bce776 25
0c06af94
KM
26/*
27 * Structure associated with user cacheing.
28 */
29struct uidinfo {
3ef0a118 30 LIST_ENTRY(uidinfo) ui_hash;
0c06af94
KM
31 uid_t ui_uid;
32 long ui_proccnt;
3ef0a118
KM
33};
34#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
35LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
36u_long uihash; /* size of hash table - 1 */
0c06af94
KM
37
38/*
3ef0a118 39 * Other process lists
0c06af94 40 */
3ef0a118
KM
41struct pidhashhead *pidhashtbl;
42u_long pidhash;
43struct pgrphashhead *pgrphashtbl;
44u_long pgrphash;
45struct proclist allproc;
46struct proclist zombproc;
47
48/*
49 * Initialize global process hashing structures.
50 */
51procinit()
0c06af94
KM
52{
53
3ef0a118
KM
54 LIST_INIT(&allproc);
55 LIST_INIT(&zombproc);
56 pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
57 pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
0c06af94
KM
58 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
59}
60
61/*
62 * Change the count associated with number of processes
63 * a given user is using.
64 */
65int
66chgproccnt(uid, diff)
67 uid_t uid;
68 int diff;
69{
3ef0a118
KM
70 register struct uidinfo *uip;
71 register struct uihashhead *uipp;
0c06af94 72
3ef0a118
KM
73 uipp = UIHASH(uid);
74 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
0c06af94
KM
75 if (uip->ui_uid == uid)
76 break;
77 if (uip) {
78 uip->ui_proccnt += diff;
79 if (uip->ui_proccnt > 0)
80 return (uip->ui_proccnt);
81 if (uip->ui_proccnt < 0)
82 panic("chgproccnt: procs < 0");
3ef0a118 83 LIST_REMOVE(uip, ui_hash);
0c06af94
KM
84 FREE(uip, M_PROC);
85 return (0);
86 }
87 if (diff <= 0) {
88 if (diff == 0)
89 return(0);
90 panic("chgproccnt: lost user");
91 }
92 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
3ef0a118 93 LIST_INSERT_HEAD(uipp, uip, ui_hash);
0c06af94
KM
94 uip->ui_uid = uid;
95 uip->ui_proccnt = diff;
96 return (diff);
97}
98
29dd101b 99/*
4147b3f6 100 * Is p an inferior of the current process?
29dd101b 101 */
4147b3f6 102inferior(p)
a2a2a0d6 103 register struct proc *p;
29dd101b 104{
2dccc728 105
bed84066
MK
106 for (; p != curproc; p = p->p_pptr)
107 if (p->p_pid == 0)
4147b3f6
BJ
108 return (0);
109 return (1);
29dd101b 110}
a2a2a0d6 111
b3ce9b0f
MK
112/*
113 * Locate a process by number
114 */
a2a2a0d6
BJ
115struct proc *
116pfind(pid)
cb84e0ab 117 register pid_t pid;
a2a2a0d6 118{
cb84e0ab 119 register struct proc *p;
a2a2a0d6 120
3ef0a118 121 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next)
a2a2a0d6
BJ
122 if (p->p_pid == pid)
123 return (p);
cb84e0ab 124 return (NULL);
a2a2a0d6 125}
1d348849 126
8fe87cbb
MT
127/*
128 * Locate a process group by number
129 */
130struct pgrp *
131pgfind(pgid)
132 register pid_t pgid;
133{
cb84e0ab 134 register struct pgrp *pgrp;
8fe87cbb 135
3ef0a118
KM
136 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0;
137 pgrp = pgrp->pg_hash.le_next)
8fe87cbb 138 if (pgrp->pg_id == pgid)
b3ce9b0f 139 return (pgrp);
cb84e0ab 140 return (NULL);
8fe87cbb
MT
141}
142
143/*
144 * Move p to a new or existing process group (and session)
145 */
bed84066 146enterpgrp(p, pgid, mksess)
8fe87cbb
MT
147 register struct proc *p;
148 pid_t pgid;
4d808bff 149 int mksess;
8fe87cbb
MT
150{
151 register struct pgrp *pgrp = pgfind(pgid);
2dccc728 152 int n;
8fe87cbb 153
944e89dc 154#ifdef DIAGNOSTIC
cb84e0ab 155 if (pgrp != NULL && mksess) /* firewalls */
bed84066 156 panic("enterpgrp: setsid into non-empty pgrp");
8fe87cbb 157 if (SESS_LEADER(p))
bed84066 158 panic("enterpgrp: session leader attempted setpgrp");
944e89dc 159#endif
2e8f8cae 160 if (pgrp == NULL) {
f9e28ab9
MT
161 pid_t savepid = p->p_pid;
162 struct proc *np;
8fe87cbb
MT
163 /*
164 * new process group
165 */
944e89dc 166#ifdef DIAGNOSTIC
8fe87cbb 167 if (p->p_pid != pgid)
bed84066 168 panic("enterpgrp: new pgrp and pid != pgid");
944e89dc 169#endif
8fe87cbb 170 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
3ef0a118 171 M_WAITOK);
f9e28ab9
MT
172 if ((np = pfind(savepid)) == NULL || np != p)
173 return (ESRCH);
8fe87cbb
MT
174 if (mksess) {
175 register struct session *sess;
f3aac35d 176
8fe87cbb
MT
177 /*
178 * new session
179 */
180 MALLOC(sess, struct session *, sizeof(struct session),
3ef0a118 181 M_SESSION, M_WAITOK);
8fe87cbb
MT
182 sess->s_leader = p;
183 sess->s_count = 1;
944e89dc
MT
184 sess->s_ttyvp = NULL;
185 sess->s_ttyp = NULL;
f3aac35d
MK
186 bcopy(p->p_session->s_login, sess->s_login,
187 sizeof(sess->s_login));
cf5ef508 188 p->p_flag &= ~P_CONTROLT;
8fe87cbb 189 pgrp->pg_session = sess;
944e89dc 190#ifdef DIAGNOSTIC
bed84066
MK
191 if (p != curproc)
192 panic("enterpgrp: mksession and p != curproc");
944e89dc 193#endif
8fe87cbb
MT
194 } else {
195 pgrp->pg_session = p->p_session;
196 pgrp->pg_session->s_count++;
197 }
198 pgrp->pg_id = pgid;
3ef0a118
KM
199 LIST_INIT(&pgrp->pg_members);
200 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
8fe87cbb 201 pgrp->pg_jobc = 0;
69ed180a 202 } else if (pgrp == p->p_pgrp)
f9e28ab9 203 return (0);
2dccc728 204
8fe87cbb 205 /*
2dccc728
MK
206 * Adjust eligibility of affected pgrps to participate in job control.
207 * Increment eligibility counts before decrementing, otherwise we
208 * could reach 0 spuriously during the first call.
8fe87cbb 209 */
2dccc728
MK
210 fixjobc(p, pgrp, 1);
211 fixjobc(p, p->p_pgrp, 0);
212
3ef0a118
KM
213 LIST_REMOVE(p, p_pglist);
214 if (p->p_pgrp->pg_members.lh_first == 0)
2dccc728 215 pgdelete(p->p_pgrp);
2dccc728 216 p->p_pgrp = pgrp;
3ef0a118 217 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
f9e28ab9 218 return (0);
8fe87cbb
MT
219}
220
221/*
222 * remove process from process group
223 */
bed84066 224leavepgrp(p)
8fe87cbb
MT
225 register struct proc *p;
226{
8fe87cbb 227
3ef0a118
KM
228 LIST_REMOVE(p, p_pglist);
229 if (p->p_pgrp->pg_members.lh_first == 0)
8fe87cbb
MT
230 pgdelete(p->p_pgrp);
231 p->p_pgrp = 0;
f9e28ab9 232 return (0);
8fe87cbb
MT
233}
234
235/*
236 * delete a process group
237 */
238pgdelete(pgrp)
239 register struct pgrp *pgrp;
240{
8fe87cbb 241
944e89dc
MT
242 if (pgrp->pg_session->s_ttyp != NULL &&
243 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
244 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
3ef0a118 245 LIST_REMOVE(pgrp, pg_hash);
8fe87cbb
MT
246 if (--pgrp->pg_session->s_count == 0)
247 FREE(pgrp->pg_session, M_SESSION);
248 FREE(pgrp, M_PGRP);
249}
250
4d808bff 251static void orphanpg();
3fb7685a 252
69ed180a 253/*
2dccc728
MK
254 * Adjust pgrp jobc counters when specified process changes process group.
255 * We count the number of processes in each process group that "qualify"
256 * the group for terminal job control (those with a parent in a different
257 * process group of the same session). If that count reaches zero, the
258 * process group becomes orphaned. Check both the specified process'
259 * process group and that of its children.
260 * entering == 0 => p is leaving specified group.
261 * entering == 1 => p is entering specified group.
69ed180a 262 */
2dccc728 263fixjobc(p, pgrp, entering)
69ed180a 264 register struct proc *p;
2dccc728
MK
265 register struct pgrp *pgrp;
266 int entering;
69ed180a 267{
2dccc728
MK
268 register struct pgrp *hispgrp;
269 register struct session *mysession = pgrp->pg_session;
69ed180a 270
2dccc728
MK
271 /*
272 * Check p's parent to see whether p qualifies its own process
273 * group; if so, adjust count for p's process group.
274 */
275 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
69ed180a 276 hispgrp->pg_session == mysession)
2dccc728
MK
277 if (entering)
278 pgrp->pg_jobc++;
279 else if (--pgrp->pg_jobc == 0)
280 orphanpg(pgrp);
69ed180a 281
2dccc728
MK
282 /*
283 * Check this process' children to see whether they qualify
284 * their process groups; if so, adjust counts for children's
285 * process groups.
286 */
3ef0a118 287 for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next)
2dccc728 288 if ((hispgrp = p->p_pgrp) != pgrp &&
69ed180a
MT
289 hispgrp->pg_session == mysession &&
290 p->p_stat != SZOMB)
2dccc728 291 if (entering)
69ed180a 292 hispgrp->pg_jobc++;
2dccc728
MK
293 else if (--hispgrp->pg_jobc == 0)
294 orphanpg(hispgrp);
295}
69ed180a 296
2dccc728
MK
297/*
298 * A process group has become orphaned;
299 * if there are any stopped processes in the group,
300 * hang-up all process in that group.
301 */
4d808bff 302static void
2dccc728
MK
303orphanpg(pg)
304 struct pgrp *pg;
305{
306 register struct proc *p;
307
3ef0a118 308 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
2dccc728 309 if (p->p_stat == SSTOP) {
3ef0a118
KM
310 for (p = pg->pg_members.lh_first; p != 0;
311 p = p->p_pglist.le_next) {
2dccc728
MK
312 psignal(p, SIGHUP);
313 psignal(p, SIGCONT);
69ed180a 314 }
2dccc728
MK
315 return;
316 }
317 }
69ed180a 318}
2dccc728 319
3ef0a118 320#ifdef DEBUG
8fe87cbb
MT
321pgrpdump()
322{
323 register struct pgrp *pgrp;
324 register struct proc *p;
325 register i;
326
3ef0a118
KM
327 for (i = 0; i <= pgrphash; i++) {
328 if (pgrp = pgrphashtbl[i].lh_first) {
329 printf("\tindx %d\n", i);
330 for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) {
331 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
332 pgrp, pgrp->pg_id, pgrp->pg_session,
333 pgrp->pg_session->s_count,
334 pgrp->pg_members.lh_first);
335 for (p = pgrp->pg_members.lh_first; p != 0;
336 p = p->p_pglist.le_next) {
337 printf("\t\tpid %d addr %x pgrp %x\n",
338 p->p_pid, p, p->p_pgrp);
339 }
340 }
8fe87cbb
MT
341 }
342 }
343}
3ef0a118 344#endif /* DEBUG */