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