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 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/cred.h>
36 #include <sys/vnode.h>
37 #include <sys/errno.h>
38 #include <sys/user.h>
39 #include <sys/mount.h>
40 #include <sys/proc.h>
41 #include <sys/signal.h>
42 #include <sys/siginfo.h>
43 #include <sys/ucontext.h>
44 #include <sys/prsystm.h>
45 #include <sys/session.h>
46 #include <sys/stream.h>
47 #include <sys/strsubr.h>
48 #include <sys/debug.h>
49
50 /*
51 * Return 1 if process pointed to by 'cp' has a parent that would
52 * prevent its process group from being orphaned, 0 otherwise
53 */
54
55 static int
pglinked(cp)56 pglinked(cp)
57 register proc_t *cp;
58 {
59 register proc_t *pp;
60
61 ASSERT(MUTEX_HELD(&pidlock));
62
63 if ((pp = cp->p_parent) != NULL &&
64 pp->p_pgidp != cp->p_pgidp &&
65 pp->p_sessp == cp->p_sessp)
66 return (1);
67 return (0);
68 }
69
70 /*
71 * Send the specified signal to all processes whose process group ID is
72 * equal to 'pgid'
73 */
74
75 void
pgsignal(pidp,sig)76 pgsignal(pidp, sig)
77 register struct pid *pidp;
78 int sig;
79 {
80 register proc_t *prp;
81
82 mutex_enter(&pidlock);
83 for (prp = pidp->pid_pglink; prp; prp = prp->p_pglink) {
84 mutex_enter(&prp->p_lock);
85 sigtoproc(prp, NULL, sig);
86 mutex_exit(&prp->p_lock);
87 }
88 mutex_exit(&pidlock);
89 }
90
91 /*
92 * similiar to pgsignal in function except that pidlock mutex is assumed
93 * to be held by the caller.
94 */
95 void
sigtopg(pidp,sig)96 sigtopg(pidp, sig)
97 register struct pid *pidp;
98 int sig;
99 {
100 register proc_t *prp;
101
102 ASSERT(MUTEX_HELD(&pidlock));
103
104 for (prp = pidp->pid_pglink; prp; prp = prp->p_pglink) {
105 mutex_enter(&prp->p_lock);
106 sigtoproc(prp, NULL, sig);
107 mutex_exit(&prp->p_lock);
108 }
109 }
110
111 /*
112 * Add a process to a process group
113 */
114
115 void
pgjoin(p,pgp)116 pgjoin(p, pgp)
117 register proc_t *p;
118 register struct pid *pgp;
119 {
120 ASSERT(MUTEX_HELD(&pidlock));
121
122 p->p_pgidp = pgp;
123
124 if (pgp->pid_pglink == NULL) {
125 ASSERT(pgp->pid_pgtail == NULL);
126 p->p_ppglink = NULL;
127 p->p_pglink = NULL;
128 pgp->pid_pglink = p;
129 pgp->pid_pgtail = p;
130 } else {
131 ASSERT(pgp->pid_pgtail != NULL);
132 if (pglinked(p)) {
133 p->p_ppglink = NULL;
134 p->p_pglink = pgp->pid_pglink;
135 pgp->pid_pglink->p_ppglink = p;
136 pgp->pid_pglink = p;
137 } else {
138 p->p_ppglink = pgp->pid_pgtail;
139 p->p_pglink = NULL;
140 pgp->pid_pgtail->p_pglink = p;
141 pgp->pid_pgtail = p;
142 }
143 }
144
145 if (pgp->pid_pglink == pgp->pid_pgtail) {
146 PID_HOLD(pgp);
147 if (pglinked(p))
148 pgp->pid_pgorphaned = 0;
149 else
150 pgp->pid_pgorphaned = 1;
151 } else if (pgp->pid_pgorphaned && pglinked(p))
152 pgp->pid_pgorphaned = 0;
153 }
154
155 void
pgexit(prp)156 pgexit(prp)
157 proc_t *prp;
158 {
159 register proc_t *p;
160 register struct pid *pgp;
161
162 ASSERT(MUTEX_HELD(&pidlock));
163
164 pgp = prp->p_pgidp;
165
166 if (pgp->pid_pglink == prp) {
167 ASSERT(prp->p_ppglink == NULL); /* must be at the front */
168 pgp->pid_pglink = prp->p_pglink;
169 }
170 if (prp->p_ppglink) {
171 prp->p_ppglink->p_pglink = prp->p_pglink;
172 }
173 if (prp->p_pglink) {
174 prp->p_pglink->p_ppglink = prp->p_ppglink;
175 }
176 if (pgp->pid_pgtail == prp) {
177 pgp->pid_pgtail = prp->p_ppglink;
178 }
179
180 prp->p_pgidp = NULL;
181 prp->p_pglink = NULL;
182 prp->p_ppglink = NULL;
183
184 if ((p = pgp->pid_pglink) == NULL) {
185 PID_RELE(pgp);
186 } else if (pgp->pid_pgorphaned == 0) {
187 do {
188 if (pglinked(p)) {
189 return;
190 }
191 } while ((p = p->p_pglink) != NULL);
192 pgp->pid_pgorphaned = 1;
193 }
194 }
195
196 /*
197 * process 'pp' is exiting - check to see if this will
198 * orphan its children's process groups
199 */
200
201 void
pgdetach(pp)202 pgdetach(pp)
203 proc_t *pp;
204 {
205 int stopped;
206 register proc_t *cp;
207 register proc_t *mp;
208 register struct pid *pgp;
209
210 ASSERT(MUTEX_HELD(&pidlock));
211
212 for (cp = pp->p_child; cp; cp = cp->p_sibling) {
213 if ((pgp = cp->p_pgidp)->pid_pgorphaned)
214 continue;
215 stopped = 0;
216 mp = pgp->pid_pglink;
217 ASSERT(mp != NULL);
218 for (;;) {
219 if (mp != pp && mp->p_parent != pp && pglinked(mp))
220 break;
221 if (!stopped && mp != curproc) {
222 mutex_enter(&mp->p_lock);
223 stopped = jobstopped(mp);
224 mutex_exit(&mp->p_lock);
225 }
226 if ((mp = mp->p_pglink) == NULL) {
227 pgp->pid_pgorphaned = 1;
228 if (stopped) {
229 sigtopg(pgp, SIGHUP);
230 sigtopg(pgp, SIGCONT);
231 }
232 break;
233 }
234 }
235 }
236 }
237
238 /*
239 * Return 1 if pgid is the process group ID of an existing process group
240 * that has members not the process group leader in it.
241 *
242 * Otherwise, return 0.
243 */
244
245 int
pgmembers(pgid)246 pgmembers(pgid)
247 register pid_t pgid;
248 {
249 register proc_t *prp;
250
251 ASSERT(MUTEX_HELD(&pidlock));
252
253 for (prp = pgfind(pgid); prp; prp = prp->p_pglink)
254 if (prp->p_pid != pgid) {
255 return (1);
256 }
257 return (0);
258 }
259