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