fix bad diagnosis of null option name
[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 *
1f3d196a 7 * @(#)kern_proc.c 8.4 (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 {
30 struct uidinfo *ui_next;
31 struct uidinfo **ui_prev;
32 uid_t ui_uid;
33 long ui_proccnt;
34} **uihashtbl;
35u_long uihash; /* size of hash table - 1 */
36#define UIHASH(uid) ((uid) & uihash)
37
38/*
39 * Allocate a hash table.
40 */
41usrinfoinit()
42{
43
44 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
45}
46
47/*
48 * Change the count associated with number of processes
49 * a given user is using.
50 */
51int
52chgproccnt(uid, diff)
53 uid_t uid;
54 int diff;
55{
56 register struct uidinfo **uipp, *uip, *uiq;
57
58 uipp = &uihashtbl[UIHASH(uid)];
59 for (uip = *uipp; uip; uip = uip->ui_next)
60 if (uip->ui_uid == uid)
61 break;
62 if (uip) {
63 uip->ui_proccnt += diff;
64 if (uip->ui_proccnt > 0)
65 return (uip->ui_proccnt);
66 if (uip->ui_proccnt < 0)
67 panic("chgproccnt: procs < 0");
68 if (uiq = uip->ui_next)
69 uiq->ui_prev = uip->ui_prev;
70 *uip->ui_prev = uiq;
71 FREE(uip, M_PROC);
72 return (0);
73 }
74 if (diff <= 0) {
75 if (diff == 0)
76 return(0);
77 panic("chgproccnt: lost user");
78 }
79 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
80 if (uiq = *uipp)
81 uiq->ui_prev = &uip->ui_next;
82 uip->ui_next = uiq;
83 uip->ui_prev = uipp;
84 *uipp = uip;
85 uip->ui_uid = uid;
86 uip->ui_proccnt = diff;
87 return (diff);
88}
89
29dd101b 90/*
4147b3f6 91 * Is p an inferior of the current process?
29dd101b 92 */
4147b3f6 93inferior(p)
a2a2a0d6 94 register struct proc *p;
29dd101b 95{
2dccc728 96
bed84066
MK
97 for (; p != curproc; p = p->p_pptr)
98 if (p->p_pid == 0)
4147b3f6
BJ
99 return (0);
100 return (1);
29dd101b 101}
a2a2a0d6 102
b3ce9b0f
MK
103/*
104 * Locate a process by number
105 */
a2a2a0d6
BJ
106struct proc *
107pfind(pid)
cb84e0ab 108 register pid_t pid;
a2a2a0d6 109{
cb84e0ab 110 register struct proc *p;
a2a2a0d6 111
cb84e0ab 112 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash)
a2a2a0d6
BJ
113 if (p->p_pid == pid)
114 return (p);
cb84e0ab 115 return (NULL);
a2a2a0d6 116}
1d348849 117
8fe87cbb
MT
118/*
119 * Locate a process group by number
120 */
121struct pgrp *
122pgfind(pgid)
123 register pid_t pgid;
124{
cb84e0ab 125 register struct pgrp *pgrp;
8fe87cbb 126
cb84e0ab
KB
127 for (pgrp = pgrphash[PIDHASH(pgid)];
128 pgrp != NULL; pgrp = pgrp->pg_hforw)
8fe87cbb 129 if (pgrp->pg_id == pgid)
b3ce9b0f 130 return (pgrp);
cb84e0ab 131 return (NULL);
8fe87cbb
MT
132}
133
134/*
135 * Move p to a new or existing process group (and session)
136 */
bed84066 137enterpgrp(p, pgid, mksess)
8fe87cbb
MT
138 register struct proc *p;
139 pid_t pgid;
4d808bff 140 int mksess;
8fe87cbb
MT
141{
142 register struct pgrp *pgrp = pgfind(pgid);
2dccc728 143 register struct proc **pp;
2dccc728 144 int n;
8fe87cbb 145
944e89dc 146#ifdef DIAGNOSTIC
cb84e0ab 147 if (pgrp != NULL && mksess) /* firewalls */
bed84066 148 panic("enterpgrp: setsid into non-empty pgrp");
8fe87cbb 149 if (SESS_LEADER(p))
bed84066 150 panic("enterpgrp: session leader attempted setpgrp");
944e89dc 151#endif
2e8f8cae 152 if (pgrp == NULL) {
f9e28ab9
MT
153 pid_t savepid = p->p_pid;
154 struct proc *np;
8fe87cbb
MT
155 /*
156 * new process group
157 */
944e89dc 158#ifdef DIAGNOSTIC
8fe87cbb 159 if (p->p_pid != pgid)
bed84066 160 panic("enterpgrp: new pgrp and pid != pgid");
944e89dc 161#endif
8fe87cbb
MT
162 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
163 M_WAITOK);
f9e28ab9
MT
164 if ((np = pfind(savepid)) == NULL || np != p)
165 return (ESRCH);
8fe87cbb
MT
166 if (mksess) {
167 register struct session *sess;
f3aac35d 168
8fe87cbb
MT
169 /*
170 * new session
171 */
172 MALLOC(sess, struct session *, sizeof(struct session),
173 M_SESSION, M_WAITOK);
174 sess->s_leader = p;
175 sess->s_count = 1;
944e89dc
MT
176 sess->s_ttyvp = NULL;
177 sess->s_ttyp = NULL;
f3aac35d
MK
178 bcopy(p->p_session->s_login, sess->s_login,
179 sizeof(sess->s_login));
cf5ef508 180 p->p_flag &= ~P_CONTROLT;
8fe87cbb 181 pgrp->pg_session = sess;
944e89dc 182#ifdef DIAGNOSTIC
bed84066
MK
183 if (p != curproc)
184 panic("enterpgrp: mksession and p != curproc");
944e89dc 185#endif
8fe87cbb
MT
186 } else {
187 pgrp->pg_session = p->p_session;
188 pgrp->pg_session->s_count++;
189 }
190 pgrp->pg_id = pgid;
2dccc728 191 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)];
8fe87cbb
MT
192 pgrphash[n] = pgrp;
193 pgrp->pg_jobc = 0;
944e89dc 194 pgrp->pg_mem = NULL;
69ed180a 195 } else if (pgrp == p->p_pgrp)
f9e28ab9 196 return (0);
2dccc728 197
8fe87cbb 198 /*
2dccc728
MK
199 * Adjust eligibility of affected pgrps to participate in job control.
200 * Increment eligibility counts before decrementing, otherwise we
201 * could reach 0 spuriously during the first call.
8fe87cbb 202 */
2dccc728
MK
203 fixjobc(p, pgrp, 1);
204 fixjobc(p, p->p_pgrp, 0);
205
8fe87cbb
MT
206 /*
207 * unlink p from old process group
208 */
f9e28ab9 209 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) {
8fe87cbb
MT
210 if (*pp == p) {
211 *pp = p->p_pgrpnxt;
f9e28ab9 212 break;
8fe87cbb 213 }
f9e28ab9
MT
214 }
215#ifdef DIAGNOSTIC
216 if (pp == NULL)
217 panic("enterpgrp: can't find p on old pgrp");
218#endif
2dccc728
MK
219 /*
220 * delete old if empty
221 */
222 if (p->p_pgrp->pg_mem == 0)
223 pgdelete(p->p_pgrp);
8fe87cbb
MT
224 /*
225 * link into new one
226 */
2dccc728 227 p->p_pgrp = pgrp;
8fe87cbb
MT
228 p->p_pgrpnxt = pgrp->pg_mem;
229 pgrp->pg_mem = p;
f9e28ab9 230 return (0);
8fe87cbb
MT
231}
232
233/*
234 * remove process from process group
235 */
bed84066 236leavepgrp(p)
8fe87cbb
MT
237 register struct proc *p;
238{
239 register struct proc **pp = &p->p_pgrp->pg_mem;
8fe87cbb 240
f9e28ab9 241 for (; *pp; pp = &(*pp)->p_pgrpnxt) {
8fe87cbb
MT
242 if (*pp == p) {
243 *pp = p->p_pgrpnxt;
f9e28ab9 244 break;
8fe87cbb 245 }
f9e28ab9
MT
246 }
247#ifdef DIAGNOSTIC
248 if (pp == NULL)
249 panic("leavepgrp: can't find p in pgrp");
250#endif
8fe87cbb
MT
251 if (!p->p_pgrp->pg_mem)
252 pgdelete(p->p_pgrp);
253 p->p_pgrp = 0;
f9e28ab9 254 return (0);
8fe87cbb
MT
255}
256
257/*
258 * delete a process group
259 */
260pgdelete(pgrp)
261 register struct pgrp *pgrp;
262{
263 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)];
264
944e89dc
MT
265 if (pgrp->pg_session->s_ttyp != NULL &&
266 pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
267 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
f9e28ab9 268 for (; *pgp; pgp = &(*pgp)->pg_hforw) {
8fe87cbb
MT
269 if (*pgp == pgrp) {
270 *pgp = pgrp->pg_hforw;
f9e28ab9 271 break;
8fe87cbb 272 }
f9e28ab9
MT
273 }
274#ifdef DIAGNOSTIC
275 if (pgp == NULL)
276 panic("pgdelete: can't find pgrp on hash chain");
277#endif
8fe87cbb
MT
278 if (--pgrp->pg_session->s_count == 0)
279 FREE(pgrp->pg_session, M_SESSION);
280 FREE(pgrp, M_PGRP);
281}
282
4d808bff 283static void orphanpg();
3fb7685a 284
69ed180a 285/*
2dccc728
MK
286 * Adjust pgrp jobc counters when specified process changes process group.
287 * We count the number of processes in each process group that "qualify"
288 * the group for terminal job control (those with a parent in a different
289 * process group of the same session). If that count reaches zero, the
290 * process group becomes orphaned. Check both the specified process'
291 * process group and that of its children.
292 * entering == 0 => p is leaving specified group.
293 * entering == 1 => p is entering specified group.
69ed180a 294 */
2dccc728 295fixjobc(p, pgrp, entering)
69ed180a 296 register struct proc *p;
2dccc728
MK
297 register struct pgrp *pgrp;
298 int entering;
69ed180a 299{
2dccc728
MK
300 register struct pgrp *hispgrp;
301 register struct session *mysession = pgrp->pg_session;
69ed180a 302
2dccc728
MK
303 /*
304 * Check p's parent to see whether p qualifies its own process
305 * group; if so, adjust count for p's process group.
306 */
307 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
69ed180a 308 hispgrp->pg_session == mysession)
2dccc728
MK
309 if (entering)
310 pgrp->pg_jobc++;
311 else if (--pgrp->pg_jobc == 0)
312 orphanpg(pgrp);
69ed180a 313
2dccc728
MK
314 /*
315 * Check this process' children to see whether they qualify
316 * their process groups; if so, adjust counts for children's
317 * process groups.
318 */
319 for (p = p->p_cptr; p; p = p->p_osptr)
320 if ((hispgrp = p->p_pgrp) != pgrp &&
69ed180a
MT
321 hispgrp->pg_session == mysession &&
322 p->p_stat != SZOMB)
2dccc728 323 if (entering)
69ed180a 324 hispgrp->pg_jobc++;
2dccc728
MK
325 else if (--hispgrp->pg_jobc == 0)
326 orphanpg(hispgrp);
327}
69ed180a 328
2dccc728
MK
329/*
330 * A process group has become orphaned;
331 * if there are any stopped processes in the group,
332 * hang-up all process in that group.
333 */
4d808bff 334static void
2dccc728
MK
335orphanpg(pg)
336 struct pgrp *pg;
337{
338 register struct proc *p;
339
340 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
341 if (p->p_stat == SSTOP) {
342 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) {
343 psignal(p, SIGHUP);
344 psignal(p, SIGCONT);
69ed180a 345 }
2dccc728
MK
346 return;
347 }
348 }
69ed180a 349}
2dccc728 350
c4ec2128 351#ifdef debug
8fe87cbb
MT
352/* DEBUG */
353pgrpdump()
354{
355 register struct pgrp *pgrp;
356 register struct proc *p;
357 register i;
358
359 for (i=0; i<PIDHSZ; i++) {
360 if (pgrphash[i]) {
361 printf("\tindx %d\n", i);
362 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) {
363 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n",
364 pgrp, pgrp->pg_id, pgrp->pg_session,
365 pgrp->pg_session->s_count, pgrp->pg_mem);
366 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) {
367 printf("\t\tpid %d addr %x pgrp %x\n",
368 p->p_pid, p, p->p_pgrp);
369 }
370 }
371
372 }
373 }
374}
c4ec2128 375#endif /* debug */