preserve login name across setsid
[unix-history] / usr / src / sys / kern / kern_proc.c
CommitLineData
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 30inferior(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
43struct proc *
44pfind(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 */
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)
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 73enterpgrp(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 147done:
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 164leavepgrp(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
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
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
198done:
199 if (--pgrp->pg_session->s_count == 0)
200 FREE(pgrp->pg_session, M_SESSION);
201 FREE(pgrp, M_PGRP);
202}
203
3fb7685a
MK
204static 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 216fixjobc(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 */
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);
69ed180a 266 }
2dccc728
MK
267 return;
268 }
269 }
69ed180a 270}
2dccc728 271
c4ec2128 272#ifdef debug
8fe87cbb
MT
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}
c4ec2128 296#endif /* debug */