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