1 /* 2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)kern_proc.c 7.16 (Berkeley) 6/28/91 34 * $Id: kern_proc.c,v 1.4 1993/06/27 06:01:40 andrew Exp $ 35 */ 36 37 #include "param.h" 38 #include "systm.h" 39 #include "kernel.h" 40 #include "proc.h" 41 #include "buf.h" 42 #include "acct.h" 43 #include "wait.h" 44 #include "file.h" 45 #include "../ufs/quota.h" 46 #include "uio.h" 47 #include "malloc.h" 48 #include "mbuf.h" 49 #include "ioctl.h" 50 #include "tty.h" 51 52 /* static */ void pgdelete __P((struct pgrp *pgrp)); 53 54 /* 55 * Is p an inferior of the current process? 56 */ 57 int 58 inferior(p) 59 register struct proc *p; 60 { 61 62 for (; p != curproc; p = p->p_pptr) 63 if (p->p_pid == 0) 64 return (0); 65 return (1); 66 } 67 68 /* 69 * Locate a process by number 70 */ 71 struct proc * 72 pfind(pid) 73 register pid; 74 { 75 register struct proc *p = pidhash[PIDHASH(pid)]; 76 77 for (; p; p = p->p_hash) 78 if (p->p_pid == pid) 79 return (p); 80 return ((struct proc *)0); 81 } 82 83 /* 84 * Locate a process group by number 85 */ 86 struct pgrp * 87 pgfind(pgid) 88 register pid_t pgid; 89 { 90 register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 91 92 for (; pgrp; pgrp = pgrp->pg_hforw) 93 if (pgrp->pg_id == pgid) 94 return (pgrp); 95 return ((struct pgrp *)0); 96 } 97 98 /* 99 * Move p to a new or existing process group (and session) 100 */ 101 void 102 enterpgrp(p, pgid, mksess) 103 register struct proc *p; 104 pid_t pgid; 105 int mksess; 106 { 107 register struct pgrp *pgrp = pgfind(pgid); 108 register struct proc **pp; 109 int n; 110 111 #ifdef DIAGNOSTIC 112 if (pgrp && mksess) /* firewalls */ 113 panic("enterpgrp: setsid into non-empty pgrp"); 114 if (SESS_LEADER(p)) 115 panic("enterpgrp: session leader attempted setpgrp"); 116 #endif 117 if (pgrp == NULL) { 118 /* 119 * new process group 120 */ 121 #ifdef DIAGNOSTIC 122 if (p->p_pid != pgid) 123 panic("enterpgrp: new pgrp and pid != pgid"); 124 #endif 125 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 126 M_WAITOK); 127 if (mksess) { 128 register struct session *sess; 129 130 /* 131 * new session 132 */ 133 MALLOC(sess, struct session *, sizeof(struct session), 134 M_SESSION, M_WAITOK); 135 sess->s_leader = p; 136 sess->s_count = 1; 137 sess->s_ttyvp = NULL; 138 sess->s_ttyp = NULL; 139 bcopy(p->p_session->s_login, sess->s_login, 140 sizeof(sess->s_login)); 141 p->p_flag &= ~SCTTY; 142 pgrp->pg_session = sess; 143 #ifdef DIAGNOSTIC 144 if (p != curproc) 145 panic("enterpgrp: mksession and p != curproc"); 146 #endif 147 } else { 148 pgrp->pg_session = p->p_session; 149 pgrp->pg_session->s_count++; 150 } 151 pgrp->pg_id = pgid; 152 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 153 pgrphash[n] = pgrp; 154 pgrp->pg_jobc = 0; 155 pgrp->pg_mem = NULL; 156 } else if (pgrp == p->p_pgrp) 157 return; 158 159 /* 160 * Adjust eligibility of affected pgrps to participate in job control. 161 * Increment eligibility counts before decrementing, otherwise we 162 * could reach 0 spuriously during the first call. 163 */ 164 fixjobc(p, pgrp, 1); 165 fixjobc(p, p->p_pgrp, 0); 166 167 /* 168 * unlink p from old process group 169 */ 170 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) 171 if (*pp == p) { 172 *pp = p->p_pgrpnxt; 173 goto done; 174 } 175 panic("enterpgrp: can't find p on old pgrp"); 176 done: 177 /* 178 * delete old if empty 179 */ 180 if (p->p_pgrp->pg_mem == 0) 181 pgdelete(p->p_pgrp); 182 /* 183 * link into new one 184 */ 185 p->p_pgrp = pgrp; 186 p->p_pgrpnxt = pgrp->pg_mem; 187 pgrp->pg_mem = p; 188 } 189 190 /* 191 * remove process from process group 192 */ 193 void 194 leavepgrp(p) 195 register struct proc *p; 196 { 197 register struct proc **pp = &p->p_pgrp->pg_mem; 198 199 for (; *pp; pp = &(*pp)->p_pgrpnxt) 200 if (*pp == p) { 201 *pp = p->p_pgrpnxt; 202 goto done; 203 } 204 panic("leavepgrp: can't find p in pgrp"); 205 done: 206 if (!p->p_pgrp->pg_mem) 207 pgdelete(p->p_pgrp); 208 p->p_pgrp = 0; 209 } 210 211 /* 212 * delete a process group [internal] 213 */ 214 void 215 pgdelete(pgrp) 216 register struct pgrp *pgrp; 217 { 218 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 219 220 if (pgrp->pg_session->s_ttyp != NULL && 221 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 222 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 223 for (; *pgp; pgp = &(*pgp)->pg_hforw) 224 if (*pgp == pgrp) { 225 *pgp = pgrp->pg_hforw; 226 goto done; 227 } 228 panic("pgdelete: can't find pgrp on hash chain"); 229 done: 230 if (--pgrp->pg_session->s_count == 0) 231 FREE(pgrp->pg_session, M_SESSION); 232 FREE(pgrp, M_PGRP); 233 } 234 235 static void orphanpg(); 236 237 /* 238 * Adjust pgrp jobc counters when specified process changes process group. 239 * We count the number of processes in each process group that "qualify" 240 * the group for terminal job control (those with a parent in a different 241 * process group of the same session). If that count reaches zero, the 242 * process group becomes orphaned. Check both the specified process' 243 * process group and that of its children. 244 * entering == 0 => p is leaving specified group. 245 * entering == 1 => p is entering specified group. 246 */ 247 void 248 fixjobc(p, pgrp, entering) 249 register struct proc *p; 250 register struct pgrp *pgrp; 251 int entering; 252 { 253 register struct pgrp *hispgrp; 254 register struct session *mysession = pgrp->pg_session; 255 256 /* 257 * Check p's parent to see whether p qualifies its own process 258 * group; if so, adjust count for p's process group. 259 */ 260 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 261 hispgrp->pg_session == mysession) 262 if (entering) 263 pgrp->pg_jobc++; 264 else if (--pgrp->pg_jobc == 0) 265 orphanpg(pgrp); 266 267 /* 268 * Check this process' children to see whether they qualify 269 * their process groups; if so, adjust counts for children's 270 * process groups. 271 */ 272 for (p = p->p_cptr; p; p = p->p_osptr) 273 if ((hispgrp = p->p_pgrp) != pgrp && 274 hispgrp->pg_session == mysession && 275 p->p_stat != SZOMB) 276 if (entering) 277 hispgrp->pg_jobc++; 278 else if (--hispgrp->pg_jobc == 0) 279 orphanpg(hispgrp); 280 } 281 282 /* 283 * A process group has become orphaned; 284 * if there are any stopped processes in the group, 285 * hang-up all process in that group. 286 */ 287 static void 288 orphanpg(pg) 289 struct pgrp *pg; 290 { 291 register struct proc *p; 292 293 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 294 if (p->p_stat == SSTOP) { 295 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 296 psignal(p, SIGHUP); 297 psignal(p, SIGCONT); 298 } 299 return; 300 } 301 } 302 } 303 304 #ifdef debug 305 /* DEBUG */ 306 void 307 pgrpdump() 308 { 309 register struct pgrp *pgrp; 310 register struct proc *p; 311 register i; 312 313 for (i=0; i<PIDHSZ; i++) { 314 if (pgrphash[i]) { 315 printf("\tindx %d\n", i); 316 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 317 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 318 pgrp, pgrp->pg_id, pgrp->pg_session, 319 pgrp->pg_session->s_count, pgrp->pg_mem); 320 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 321 printf("\t\tpid %d addr %x pgrp %x\n", 322 p->p_pid, p, p->p_pgrp); 323 } 324 } 325 326 } 327 } 328 } 329 #endif /* debug */ 330