xref: /onnv-gate/usr/src/uts/common/os/pgrp.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate 
26*0Sstevel@tonic-gate /*
27*0Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
28*0Sstevel@tonic-gate  * All rights reserved.
29*0Sstevel@tonic-gate  */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <sys/types.h>
34*0Sstevel@tonic-gate #include <sys/sysmacros.h>
35*0Sstevel@tonic-gate #include <sys/param.h>
36*0Sstevel@tonic-gate #include <sys/systm.h>
37*0Sstevel@tonic-gate #include <sys/cred.h>
38*0Sstevel@tonic-gate #include <sys/vnode.h>
39*0Sstevel@tonic-gate #include <sys/errno.h>
40*0Sstevel@tonic-gate #include <sys/user.h>
41*0Sstevel@tonic-gate #include <sys/mount.h>
42*0Sstevel@tonic-gate #include <sys/proc.h>
43*0Sstevel@tonic-gate #include <sys/signal.h>
44*0Sstevel@tonic-gate #include <sys/siginfo.h>
45*0Sstevel@tonic-gate #include <sys/ucontext.h>
46*0Sstevel@tonic-gate #include <sys/prsystm.h>
47*0Sstevel@tonic-gate #include <sys/session.h>
48*0Sstevel@tonic-gate #include <sys/stream.h>
49*0Sstevel@tonic-gate #include <sys/strsubr.h>
50*0Sstevel@tonic-gate #include <sys/debug.h>
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate /*
53*0Sstevel@tonic-gate  * Return 1 if process pointed to by 'cp' has a parent that would
54*0Sstevel@tonic-gate  * prevent its process group from being orphaned, 0 otherwise
55*0Sstevel@tonic-gate  */
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate static int
58*0Sstevel@tonic-gate pglinked(cp)
59*0Sstevel@tonic-gate 	register proc_t *cp;
60*0Sstevel@tonic-gate {
61*0Sstevel@tonic-gate 	register proc_t *pp;
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate 	if ((pp = cp->p_parent) != NULL &&
66*0Sstevel@tonic-gate 	    pp->p_pgidp != cp->p_pgidp &&
67*0Sstevel@tonic-gate 	    pp->p_sessp == cp->p_sessp)
68*0Sstevel@tonic-gate 		return (1);
69*0Sstevel@tonic-gate 	return (0);
70*0Sstevel@tonic-gate }
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate /*
73*0Sstevel@tonic-gate  * Send the specified signal to all processes whose process group ID is
74*0Sstevel@tonic-gate  * equal to 'pgid'
75*0Sstevel@tonic-gate  */
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate void
78*0Sstevel@tonic-gate pgsignal(pidp, sig)
79*0Sstevel@tonic-gate 	register struct pid *pidp;
80*0Sstevel@tonic-gate 	int sig;
81*0Sstevel@tonic-gate {
82*0Sstevel@tonic-gate 	register proc_t *prp;
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	mutex_enter(&pidlock);
85*0Sstevel@tonic-gate 	for (prp = pidp->pid_pglink; prp; prp = prp->p_pglink) {
86*0Sstevel@tonic-gate 		mutex_enter(&prp->p_lock);
87*0Sstevel@tonic-gate 		sigtoproc(prp, NULL, sig);
88*0Sstevel@tonic-gate 		mutex_exit(&prp->p_lock);
89*0Sstevel@tonic-gate 	}
90*0Sstevel@tonic-gate 	mutex_exit(&pidlock);
91*0Sstevel@tonic-gate }
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate /*
94*0Sstevel@tonic-gate  * similiar to pgsignal in function except that pidlock mutex is assumed
95*0Sstevel@tonic-gate  * to be held by the caller.
96*0Sstevel@tonic-gate  */
97*0Sstevel@tonic-gate void
98*0Sstevel@tonic-gate sigtopg(pidp, sig)
99*0Sstevel@tonic-gate 	register struct pid *pidp;
100*0Sstevel@tonic-gate 	int sig;
101*0Sstevel@tonic-gate {
102*0Sstevel@tonic-gate 	register proc_t *prp;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 	for (prp = pidp->pid_pglink; prp; prp = prp->p_pglink) {
107*0Sstevel@tonic-gate 		mutex_enter(&prp->p_lock);
108*0Sstevel@tonic-gate 		sigtoproc(prp, NULL, sig);
109*0Sstevel@tonic-gate 		mutex_exit(&prp->p_lock);
110*0Sstevel@tonic-gate 	}
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate /*
114*0Sstevel@tonic-gate  * Add a process to a process group
115*0Sstevel@tonic-gate  */
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate void
118*0Sstevel@tonic-gate pgjoin(p, pgp)
119*0Sstevel@tonic-gate 	register proc_t *p;
120*0Sstevel@tonic-gate 	register struct pid *pgp;
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	p->p_ppglink = NULL;
125*0Sstevel@tonic-gate 	p->p_pglink = pgp->pid_pglink;
126*0Sstevel@tonic-gate 	if (pgp->pid_pglink) {
127*0Sstevel@tonic-gate 		pgp->pid_pglink->p_ppglink = p;
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 	pgp->pid_pglink = p;
130*0Sstevel@tonic-gate 	p->p_pgidp = pgp;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	if (p->p_pglink == NULL) {
133*0Sstevel@tonic-gate 		PID_HOLD(pgp);
134*0Sstevel@tonic-gate 		if (pglinked(p))
135*0Sstevel@tonic-gate 			pgp->pid_pgorphaned = 0;
136*0Sstevel@tonic-gate 		else
137*0Sstevel@tonic-gate 			pgp->pid_pgorphaned = 1;
138*0Sstevel@tonic-gate 	} else if (pgp->pid_pgorphaned && pglinked(p))
139*0Sstevel@tonic-gate 		pgp->pid_pgorphaned = 0;
140*0Sstevel@tonic-gate }
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate void
143*0Sstevel@tonic-gate pgexit(prp)
144*0Sstevel@tonic-gate 	proc_t *prp;
145*0Sstevel@tonic-gate {
146*0Sstevel@tonic-gate 	register proc_t *p;
147*0Sstevel@tonic-gate 	register struct pid *pgp;
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	pgp = prp->p_pgidp;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	if (pgp->pid_pglink == prp) {
154*0Sstevel@tonic-gate 		ASSERT(prp->p_ppglink == NULL); /* must be at the front */
155*0Sstevel@tonic-gate 		pgp->pid_pglink = prp->p_pglink;
156*0Sstevel@tonic-gate 	}
157*0Sstevel@tonic-gate 	if (prp->p_ppglink) {
158*0Sstevel@tonic-gate 		prp->p_ppglink->p_pglink = prp->p_pglink;
159*0Sstevel@tonic-gate 	}
160*0Sstevel@tonic-gate 	if (prp->p_pglink) {
161*0Sstevel@tonic-gate 		prp->p_pglink->p_ppglink = prp->p_ppglink;
162*0Sstevel@tonic-gate 	}
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	prp->p_pgidp = NULL;
165*0Sstevel@tonic-gate 	prp->p_pglink = NULL;
166*0Sstevel@tonic-gate 	prp->p_ppglink = NULL;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	if ((p = pgp->pid_pglink) == NULL) {
169*0Sstevel@tonic-gate 		PID_RELE(pgp);
170*0Sstevel@tonic-gate 	} else if (pgp->pid_pgorphaned == 0) {
171*0Sstevel@tonic-gate 		do {
172*0Sstevel@tonic-gate 			if (pglinked(p)) {
173*0Sstevel@tonic-gate 				return;
174*0Sstevel@tonic-gate 			}
175*0Sstevel@tonic-gate 		} while ((p = p->p_pglink) != NULL);
176*0Sstevel@tonic-gate 		pgp->pid_pgorphaned = 1;
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate /*
181*0Sstevel@tonic-gate  * process 'pp' is exiting - check to see if this will
182*0Sstevel@tonic-gate  * orphan its children's process groups
183*0Sstevel@tonic-gate  */
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate void
186*0Sstevel@tonic-gate pgdetach(pp)
187*0Sstevel@tonic-gate 	proc_t *pp;
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	int stopped;
190*0Sstevel@tonic-gate 	register proc_t *cp;
191*0Sstevel@tonic-gate 	register proc_t *mp;
192*0Sstevel@tonic-gate 	register struct pid *pgp;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	for (cp = pp->p_child; cp; cp = cp->p_sibling) {
197*0Sstevel@tonic-gate 		if ((pgp = cp->p_pgidp)->pid_pgorphaned)
198*0Sstevel@tonic-gate 			continue;
199*0Sstevel@tonic-gate 		stopped = 0;
200*0Sstevel@tonic-gate 		mp = pgp->pid_pglink;
201*0Sstevel@tonic-gate 		ASSERT(mp != NULL);
202*0Sstevel@tonic-gate 		for (;;) {
203*0Sstevel@tonic-gate 			if (mp != pp && mp->p_parent != pp && pglinked(mp))
204*0Sstevel@tonic-gate 				break;
205*0Sstevel@tonic-gate 			if (!stopped && mp != curproc) {
206*0Sstevel@tonic-gate 				mutex_enter(&mp->p_lock);
207*0Sstevel@tonic-gate 				stopped = jobstopped(mp);
208*0Sstevel@tonic-gate 				mutex_exit(&mp->p_lock);
209*0Sstevel@tonic-gate 			}
210*0Sstevel@tonic-gate 			if ((mp = mp->p_pglink) == NULL) {
211*0Sstevel@tonic-gate 				pgp->pid_pgorphaned = 1;
212*0Sstevel@tonic-gate 				if (stopped) {
213*0Sstevel@tonic-gate 					sigtopg(pgp, SIGHUP);
214*0Sstevel@tonic-gate 					sigtopg(pgp, SIGCONT);
215*0Sstevel@tonic-gate 				}
216*0Sstevel@tonic-gate 				break;
217*0Sstevel@tonic-gate 			}
218*0Sstevel@tonic-gate 		}
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate }
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate /*
223*0Sstevel@tonic-gate  * Return 1 if pgid is the process group ID of an existing process group
224*0Sstevel@tonic-gate  *	that has members not the process group leader in it.
225*0Sstevel@tonic-gate  *
226*0Sstevel@tonic-gate  * Otherwise, return 0.
227*0Sstevel@tonic-gate  */
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate int
230*0Sstevel@tonic-gate pgmembers(pgid)
231*0Sstevel@tonic-gate 	register pid_t pgid;
232*0Sstevel@tonic-gate {
233*0Sstevel@tonic-gate 	register proc_t *prp;
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pidlock));
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	for (prp = pgfind(pgid); prp; prp = prp->p_pglink)
238*0Sstevel@tonic-gate 		if (prp->p_pid != pgid) {
239*0Sstevel@tonic-gate 			return (1);
240*0Sstevel@tonic-gate 		}
241*0Sstevel@tonic-gate 	return (0);
242*0Sstevel@tonic-gate }
243