xref: /illumos-gate/usr/src/uts/common/os/pgrp.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2005 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
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_pgidp = pgp;
125 
126 	if (pgp->pid_pglink == NULL) {
127 		ASSERT(pgp->pid_pgtail == NULL);
128 		p->p_ppglink = NULL;
129 		p->p_pglink = NULL;
130 		pgp->pid_pglink = p;
131 		pgp->pid_pgtail = p;
132 	} else 	{
133 		ASSERT(pgp->pid_pgtail != NULL);
134 		if (pglinked(p)) {
135 			p->p_ppglink = NULL;
136 			p->p_pglink = pgp->pid_pglink;
137 			pgp->pid_pglink->p_ppglink = p;
138 			pgp->pid_pglink = p;
139 		} else {
140 			p->p_ppglink = pgp->pid_pgtail;
141 			p->p_pglink = NULL;
142 			pgp->pid_pgtail->p_pglink = p;
143 			pgp->pid_pgtail = p;
144 		}
145 	}
146 
147 	if (pgp->pid_pglink == pgp->pid_pgtail) {
148 		PID_HOLD(pgp);
149 		if (pglinked(p))
150 			pgp->pid_pgorphaned = 0;
151 		else
152 			pgp->pid_pgorphaned = 1;
153 	} else if (pgp->pid_pgorphaned && pglinked(p))
154 		pgp->pid_pgorphaned = 0;
155 }
156 
157 void
158 pgexit(prp)
159 	proc_t *prp;
160 {
161 	register proc_t *p;
162 	register struct pid *pgp;
163 
164 	ASSERT(MUTEX_HELD(&pidlock));
165 
166 	pgp = prp->p_pgidp;
167 
168 	if (pgp->pid_pglink == prp) {
169 		ASSERT(prp->p_ppglink == NULL); /* must be at the front */
170 		pgp->pid_pglink = prp->p_pglink;
171 	}
172 	if (prp->p_ppglink) {
173 		prp->p_ppglink->p_pglink = prp->p_pglink;
174 	}
175 	if (prp->p_pglink) {
176 		prp->p_pglink->p_ppglink = prp->p_ppglink;
177 	}
178 	if (pgp->pid_pgtail == prp) {
179 		pgp->pid_pgtail = prp->p_ppglink;
180 	}
181 
182 	prp->p_pgidp = NULL;
183 	prp->p_pglink = NULL;
184 	prp->p_ppglink = NULL;
185 
186 	if ((p = pgp->pid_pglink) == NULL) {
187 		PID_RELE(pgp);
188 	} else if (pgp->pid_pgorphaned == 0) {
189 		do {
190 			if (pglinked(p)) {
191 				return;
192 			}
193 		} while ((p = p->p_pglink) != NULL);
194 		pgp->pid_pgorphaned = 1;
195 	}
196 }
197 
198 /*
199  * process 'pp' is exiting - check to see if this will
200  * orphan its children's process groups
201  */
202 
203 void
204 pgdetach(pp)
205 	proc_t *pp;
206 {
207 	int stopped;
208 	register proc_t *cp;
209 	register proc_t *mp;
210 	register struct pid *pgp;
211 
212 	ASSERT(MUTEX_HELD(&pidlock));
213 
214 	for (cp = pp->p_child; cp; cp = cp->p_sibling) {
215 		if ((pgp = cp->p_pgidp)->pid_pgorphaned)
216 			continue;
217 		stopped = 0;
218 		mp = pgp->pid_pglink;
219 		ASSERT(mp != NULL);
220 		for (;;) {
221 			if (mp != pp && mp->p_parent != pp && pglinked(mp))
222 				break;
223 			if (!stopped && mp != curproc) {
224 				mutex_enter(&mp->p_lock);
225 				stopped = jobstopped(mp);
226 				mutex_exit(&mp->p_lock);
227 			}
228 			if ((mp = mp->p_pglink) == NULL) {
229 				pgp->pid_pgorphaned = 1;
230 				if (stopped) {
231 					sigtopg(pgp, SIGHUP);
232 					sigtopg(pgp, SIGCONT);
233 				}
234 				break;
235 			}
236 		}
237 	}
238 }
239 
240 /*
241  * Return 1 if pgid is the process group ID of an existing process group
242  *	that has members not the process group leader in it.
243  *
244  * Otherwise, return 0.
245  */
246 
247 int
248 pgmembers(pgid)
249 	register pid_t pgid;
250 {
251 	register proc_t *prp;
252 
253 	ASSERT(MUTEX_HELD(&pidlock));
254 
255 	for (prp = pgfind(pgid); prp; prp = prp->p_pglink)
256 		if (prp->p_pid != pgid) {
257 			return (1);
258 		}
259 	return (0);
260 }
261