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