1/* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. 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 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
| 1/* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. 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 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
|
53void pgdelete __P((struct pgrp *)); 54void fixjobc __P((struct proc *, struct pgrp *, int)); 55 56/* 57 * Structure associated with user cacheing. 58 */ 59struct uidinfo { 60 struct uidinfo *ui_next; 61 struct uidinfo **ui_prev; 62 uid_t ui_uid; 63 long ui_proccnt; 64} **uihashtbl; 65u_long uihash; /* size of hash table - 1 */ 66#define UIHASH(uid) ((uid) & uihash) 67 68/* 69 * Allocate a hash table. 70 */ 71void 72usrinfoinit() 73{ 74 75 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 76} 77 78/* 79 * Change the count associated with number of processes 80 * a given user is using. 81 */ 82int 83chgproccnt(uid, diff) 84 uid_t uid; 85 int diff; 86{ 87 register struct uidinfo **uipp, *uip, *uiq; 88 89 uipp = &uihashtbl[UIHASH(uid)]; 90 for (uip = *uipp; uip; uip = uip->ui_next) 91 if (uip->ui_uid == uid) 92 break; 93 if (uip) { 94 uip->ui_proccnt += diff; 95 if (uip->ui_proccnt > 0) 96 return (uip->ui_proccnt); 97 if (uip->ui_proccnt < 0) 98 panic("chgproccnt: procs < 0"); 99 if (uiq = uip->ui_next) 100 uiq->ui_prev = uip->ui_prev; 101 *uip->ui_prev = uiq; 102 FREE(uip, M_PROC); 103 return (0); 104 } 105 if (diff <= 0) { 106 if (diff == 0) 107 return(0); 108 panic("chgproccnt: lost user"); 109 } 110 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 111 if (uiq = *uipp) 112 uiq->ui_prev = &uip->ui_next; 113 uip->ui_next = uiq; 114 uip->ui_prev = uipp; 115 *uipp = uip; 116 uip->ui_uid = uid; 117 uip->ui_proccnt = diff; 118 return (diff); 119} 120 121/* 122 * Is p an inferior of the current process? 123 */ 124int 125inferior(p) 126 register struct proc *p; 127{ 128 129 for (; p != curproc; p = p->p_pptr) 130 if (p->p_pid == 0) 131 return (0); 132 return (1); 133} 134 135/* 136 * Locate a process by number 137 */ 138struct proc * 139pfind(pid) 140 register pid_t pid; 141{ 142 register struct proc *p; 143 144 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 145 if (p->p_pid == pid) 146 return (p); 147 return (NULL); 148} 149 150/* 151 * Locate a process group by number 152 */ 153struct pgrp * 154pgfind(pgid) 155 register pid_t pgid; 156{ 157 register struct pgrp *pgrp; 158 159 for (pgrp = pgrphash[PIDHASH(pgid)]; 160 pgrp != NULL; pgrp = pgrp->pg_hforw) 161 if (pgrp->pg_id == pgid) 162 return (pgrp); 163 return (NULL); 164} 165 166/* 167 * Move p to a new or existing process group (and session) 168 */ 169int 170enterpgrp(p, pgid, mksess) 171 register struct proc *p; 172 pid_t pgid; 173 int mksess; 174{ 175 register struct pgrp *pgrp = pgfind(pgid); 176 register struct proc **pp; 177 int n; 178 179#ifdef DIAGNOSTIC 180 if (pgrp != NULL && mksess) /* firewalls */ 181 panic("enterpgrp: setsid into non-empty pgrp"); 182 if (SESS_LEADER(p)) 183 panic("enterpgrp: session leader attempted setpgrp"); 184#endif 185 if (pgrp == NULL) { 186 pid_t savepid = p->p_pid; 187 struct proc *np; 188 /* 189 * new process group 190 */ 191#ifdef DIAGNOSTIC 192 if (p->p_pid != pgid) 193 panic("enterpgrp: new pgrp and pid != pgid"); 194#endif 195 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 196 M_WAITOK); 197 if ((np = pfind(savepid)) == NULL || np != p) 198 return (ESRCH); 199 if (mksess) { 200 register struct session *sess; 201 202 /* 203 * new session 204 */ 205 MALLOC(sess, struct session *, sizeof(struct session), 206 M_SESSION, M_WAITOK); 207 sess->s_leader = p; 208 sess->s_count = 1; 209 sess->s_ttyvp = NULL; 210 sess->s_ttyp = NULL; 211 bcopy(p->p_session->s_login, sess->s_login, 212 sizeof(sess->s_login)); 213 p->p_flag &= ~P_CONTROLT; 214 pgrp->pg_session = sess; 215#ifdef DIAGNOSTIC 216 if (p != curproc) 217 panic("enterpgrp: mksession and p != curproc"); 218#endif 219 } else { 220 pgrp->pg_session = p->p_session; 221 pgrp->pg_session->s_count++; 222 } 223 pgrp->pg_id = pgid; 224 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 225 pgrphash[n] = pgrp; 226 pgrp->pg_jobc = 0; 227 pgrp->pg_mem = NULL; 228 } else if (pgrp == p->p_pgrp) 229 return (0); 230 231 /* 232 * Adjust eligibility of affected pgrps to participate in job control. 233 * Increment eligibility counts before decrementing, otherwise we 234 * could reach 0 spuriously during the first call. 235 */ 236 fixjobc(p, pgrp, 1); 237 fixjobc(p, p->p_pgrp, 0); 238 239 /* 240 * unlink p from old process group 241 */ 242 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 243 if (*pp == p) { 244 *pp = p->p_pgrpnxt; 245 break; 246 } 247 } 248#ifdef DIAGNOSTIC 249 if (pp == NULL) 250 panic("enterpgrp: can't find p on old pgrp"); 251#endif 252 /* 253 * delete old if empty 254 */ 255 if (p->p_pgrp->pg_mem == 0) 256 pgdelete(p->p_pgrp); 257 /* 258 * link into new one 259 */ 260 p->p_pgrp = pgrp; 261 p->p_pgrpnxt = pgrp->pg_mem; 262 pgrp->pg_mem = p; 263 return (0); 264} 265 266/* 267 * remove process from process group 268 */ 269int 270leavepgrp(p) 271 register struct proc *p; 272{ 273 register struct proc **pp = &p->p_pgrp->pg_mem; 274 275 for (; *pp; pp = &(*pp)->p_pgrpnxt) { 276 if (*pp == p) { 277 *pp = p->p_pgrpnxt; 278 break; 279 } 280 } 281#ifdef DIAGNOSTIC 282 if (pp == NULL) 283 panic("leavepgrp: can't find p in pgrp"); 284#endif 285 if (!p->p_pgrp->pg_mem) 286 pgdelete(p->p_pgrp); 287 p->p_pgrp = 0; 288 return (0); 289} 290 291/* 292 * delete a process group 293 */ 294void 295pgdelete(pgrp) 296 register struct pgrp *pgrp; 297{ 298 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 299 300 if (pgrp->pg_session->s_ttyp != NULL && 301 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 302 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 303 for (; *pgp; pgp = &(*pgp)->pg_hforw) { 304 if (*pgp == pgrp) { 305 *pgp = pgrp->pg_hforw; 306 break; 307 } 308 } 309#ifdef DIAGNOSTIC 310 if (pgp == NULL) 311 panic("pgdelete: can't find pgrp on hash chain"); 312#endif 313 if (--pgrp->pg_session->s_count == 0) 314 FREE(pgrp->pg_session, M_SESSION); 315 FREE(pgrp, M_PGRP); 316} 317 318static void orphanpg(); 319 320/* 321 * Adjust pgrp jobc counters when specified process changes process group. 322 * We count the number of processes in each process group that "qualify" 323 * the group for terminal job control (those with a parent in a different 324 * process group of the same session). If that count reaches zero, the 325 * process group becomes orphaned. Check both the specified process' 326 * process group and that of its children. 327 * entering == 0 => p is leaving specified group. 328 * entering == 1 => p is entering specified group. 329 */ 330void 331fixjobc(p, pgrp, entering) 332 register struct proc *p; 333 register struct pgrp *pgrp; 334 int entering; 335{ 336 register struct pgrp *hispgrp; 337 register struct session *mysession = pgrp->pg_session; 338 339 /* 340 * Check p's parent to see whether p qualifies its own process 341 * group; if so, adjust count for p's process group. 342 */ 343 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 344 hispgrp->pg_session == mysession) 345 if (entering) 346 pgrp->pg_jobc++; 347 else if (--pgrp->pg_jobc == 0) 348 orphanpg(pgrp); 349 350 /* 351 * Check this process' children to see whether they qualify 352 * their process groups; if so, adjust counts for children's 353 * process groups. 354 */ 355 for (p = p->p_cptr; p; p = p->p_osptr) 356 if ((hispgrp = p->p_pgrp) != pgrp && 357 hispgrp->pg_session == mysession && 358 p->p_stat != SZOMB) 359 if (entering) 360 hispgrp->pg_jobc++; 361 else if (--hispgrp->pg_jobc == 0) 362 orphanpg(hispgrp); 363} 364 365/* 366 * A process group has become orphaned; 367 * if there are any stopped processes in the group, 368 * hang-up all process in that group. 369 */ 370static void 371orphanpg(pg) 372 struct pgrp *pg; 373{ 374 register struct proc *p; 375 376 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 377 if (p->p_stat == SSTOP) { 378 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 379 psignal(p, SIGHUP); 380 psignal(p, SIGCONT); 381 } 382 return; 383 } 384 } 385} 386 387#ifdef debug 388/* DEBUG */ 389pgrpdump() 390{ 391 register struct pgrp *pgrp; 392 register struct proc *p; 393 register i; 394 395 for (i=0; i<PIDHSZ; i++) { 396 if (pgrphash[i]) { 397 printf("\tindx %d\n", i); 398 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 399 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 400 pgrp, pgrp->pg_id, pgrp->pg_session, 401 pgrp->pg_session->s_count, pgrp->pg_mem); 402 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 403 printf("\t\tpid %d addr %x pgrp %x\n", 404 p->p_pid, p, p->p_pgrp); 405 } 406 } 407 408 } 409 } 410} 411#endif /* debug */
| 56void pgdelete __P((struct pgrp *)); 57void fixjobc __P((struct proc *, struct pgrp *, int)); 58 59/* 60 * Structure associated with user cacheing. 61 */ 62struct uidinfo { 63 struct uidinfo *ui_next; 64 struct uidinfo **ui_prev; 65 uid_t ui_uid; 66 long ui_proccnt; 67} **uihashtbl; 68u_long uihash; /* size of hash table - 1 */ 69#define UIHASH(uid) ((uid) & uihash) 70 71/* 72 * Allocate a hash table. 73 */ 74void 75usrinfoinit() 76{ 77 78 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 79} 80 81/* 82 * Change the count associated with number of processes 83 * a given user is using. 84 */ 85int 86chgproccnt(uid, diff) 87 uid_t uid; 88 int diff; 89{ 90 register struct uidinfo **uipp, *uip, *uiq; 91 92 uipp = &uihashtbl[UIHASH(uid)]; 93 for (uip = *uipp; uip; uip = uip->ui_next) 94 if (uip->ui_uid == uid) 95 break; 96 if (uip) { 97 uip->ui_proccnt += diff; 98 if (uip->ui_proccnt > 0) 99 return (uip->ui_proccnt); 100 if (uip->ui_proccnt < 0) 101 panic("chgproccnt: procs < 0"); 102 if (uiq = uip->ui_next) 103 uiq->ui_prev = uip->ui_prev; 104 *uip->ui_prev = uiq; 105 FREE(uip, M_PROC); 106 return (0); 107 } 108 if (diff <= 0) { 109 if (diff == 0) 110 return(0); 111 panic("chgproccnt: lost user"); 112 } 113 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 114 if (uiq = *uipp) 115 uiq->ui_prev = &uip->ui_next; 116 uip->ui_next = uiq; 117 uip->ui_prev = uipp; 118 *uipp = uip; 119 uip->ui_uid = uid; 120 uip->ui_proccnt = diff; 121 return (diff); 122} 123 124/* 125 * Is p an inferior of the current process? 126 */ 127int 128inferior(p) 129 register struct proc *p; 130{ 131 132 for (; p != curproc; p = p->p_pptr) 133 if (p->p_pid == 0) 134 return (0); 135 return (1); 136} 137 138/* 139 * Locate a process by number 140 */ 141struct proc * 142pfind(pid) 143 register pid_t pid; 144{ 145 register struct proc *p; 146 147 for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 148 if (p->p_pid == pid) 149 return (p); 150 return (NULL); 151} 152 153/* 154 * Locate a process group by number 155 */ 156struct pgrp * 157pgfind(pgid) 158 register pid_t pgid; 159{ 160 register struct pgrp *pgrp; 161 162 for (pgrp = pgrphash[PIDHASH(pgid)]; 163 pgrp != NULL; pgrp = pgrp->pg_hforw) 164 if (pgrp->pg_id == pgid) 165 return (pgrp); 166 return (NULL); 167} 168 169/* 170 * Move p to a new or existing process group (and session) 171 */ 172int 173enterpgrp(p, pgid, mksess) 174 register struct proc *p; 175 pid_t pgid; 176 int mksess; 177{ 178 register struct pgrp *pgrp = pgfind(pgid); 179 register struct proc **pp; 180 int n; 181 182#ifdef DIAGNOSTIC 183 if (pgrp != NULL && mksess) /* firewalls */ 184 panic("enterpgrp: setsid into non-empty pgrp"); 185 if (SESS_LEADER(p)) 186 panic("enterpgrp: session leader attempted setpgrp"); 187#endif 188 if (pgrp == NULL) { 189 pid_t savepid = p->p_pid; 190 struct proc *np; 191 /* 192 * new process group 193 */ 194#ifdef DIAGNOSTIC 195 if (p->p_pid != pgid) 196 panic("enterpgrp: new pgrp and pid != pgid"); 197#endif 198 MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 199 M_WAITOK); 200 if ((np = pfind(savepid)) == NULL || np != p) 201 return (ESRCH); 202 if (mksess) { 203 register struct session *sess; 204 205 /* 206 * new session 207 */ 208 MALLOC(sess, struct session *, sizeof(struct session), 209 M_SESSION, M_WAITOK); 210 sess->s_leader = p; 211 sess->s_count = 1; 212 sess->s_ttyvp = NULL; 213 sess->s_ttyp = NULL; 214 bcopy(p->p_session->s_login, sess->s_login, 215 sizeof(sess->s_login)); 216 p->p_flag &= ~P_CONTROLT; 217 pgrp->pg_session = sess; 218#ifdef DIAGNOSTIC 219 if (p != curproc) 220 panic("enterpgrp: mksession and p != curproc"); 221#endif 222 } else { 223 pgrp->pg_session = p->p_session; 224 pgrp->pg_session->s_count++; 225 } 226 pgrp->pg_id = pgid; 227 pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 228 pgrphash[n] = pgrp; 229 pgrp->pg_jobc = 0; 230 pgrp->pg_mem = NULL; 231 } else if (pgrp == p->p_pgrp) 232 return (0); 233 234 /* 235 * Adjust eligibility of affected pgrps to participate in job control. 236 * Increment eligibility counts before decrementing, otherwise we 237 * could reach 0 spuriously during the first call. 238 */ 239 fixjobc(p, pgrp, 1); 240 fixjobc(p, p->p_pgrp, 0); 241 242 /* 243 * unlink p from old process group 244 */ 245 for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 246 if (*pp == p) { 247 *pp = p->p_pgrpnxt; 248 break; 249 } 250 } 251#ifdef DIAGNOSTIC 252 if (pp == NULL) 253 panic("enterpgrp: can't find p on old pgrp"); 254#endif 255 /* 256 * delete old if empty 257 */ 258 if (p->p_pgrp->pg_mem == 0) 259 pgdelete(p->p_pgrp); 260 /* 261 * link into new one 262 */ 263 p->p_pgrp = pgrp; 264 p->p_pgrpnxt = pgrp->pg_mem; 265 pgrp->pg_mem = p; 266 return (0); 267} 268 269/* 270 * remove process from process group 271 */ 272int 273leavepgrp(p) 274 register struct proc *p; 275{ 276 register struct proc **pp = &p->p_pgrp->pg_mem; 277 278 for (; *pp; pp = &(*pp)->p_pgrpnxt) { 279 if (*pp == p) { 280 *pp = p->p_pgrpnxt; 281 break; 282 } 283 } 284#ifdef DIAGNOSTIC 285 if (pp == NULL) 286 panic("leavepgrp: can't find p in pgrp"); 287#endif 288 if (!p->p_pgrp->pg_mem) 289 pgdelete(p->p_pgrp); 290 p->p_pgrp = 0; 291 return (0); 292} 293 294/* 295 * delete a process group 296 */ 297void 298pgdelete(pgrp) 299 register struct pgrp *pgrp; 300{ 301 register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 302 303 if (pgrp->pg_session->s_ttyp != NULL && 304 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 305 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 306 for (; *pgp; pgp = &(*pgp)->pg_hforw) { 307 if (*pgp == pgrp) { 308 *pgp = pgrp->pg_hforw; 309 break; 310 } 311 } 312#ifdef DIAGNOSTIC 313 if (pgp == NULL) 314 panic("pgdelete: can't find pgrp on hash chain"); 315#endif 316 if (--pgrp->pg_session->s_count == 0) 317 FREE(pgrp->pg_session, M_SESSION); 318 FREE(pgrp, M_PGRP); 319} 320 321static void orphanpg(); 322 323/* 324 * Adjust pgrp jobc counters when specified process changes process group. 325 * We count the number of processes in each process group that "qualify" 326 * the group for terminal job control (those with a parent in a different 327 * process group of the same session). If that count reaches zero, the 328 * process group becomes orphaned. Check both the specified process' 329 * process group and that of its children. 330 * entering == 0 => p is leaving specified group. 331 * entering == 1 => p is entering specified group. 332 */ 333void 334fixjobc(p, pgrp, entering) 335 register struct proc *p; 336 register struct pgrp *pgrp; 337 int entering; 338{ 339 register struct pgrp *hispgrp; 340 register struct session *mysession = pgrp->pg_session; 341 342 /* 343 * Check p's parent to see whether p qualifies its own process 344 * group; if so, adjust count for p's process group. 345 */ 346 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 347 hispgrp->pg_session == mysession) 348 if (entering) 349 pgrp->pg_jobc++; 350 else if (--pgrp->pg_jobc == 0) 351 orphanpg(pgrp); 352 353 /* 354 * Check this process' children to see whether they qualify 355 * their process groups; if so, adjust counts for children's 356 * process groups. 357 */ 358 for (p = p->p_cptr; p; p = p->p_osptr) 359 if ((hispgrp = p->p_pgrp) != pgrp && 360 hispgrp->pg_session == mysession && 361 p->p_stat != SZOMB) 362 if (entering) 363 hispgrp->pg_jobc++; 364 else if (--hispgrp->pg_jobc == 0) 365 orphanpg(hispgrp); 366} 367 368/* 369 * A process group has become orphaned; 370 * if there are any stopped processes in the group, 371 * hang-up all process in that group. 372 */ 373static void 374orphanpg(pg) 375 struct pgrp *pg; 376{ 377 register struct proc *p; 378 379 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 380 if (p->p_stat == SSTOP) { 381 for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 382 psignal(p, SIGHUP); 383 psignal(p, SIGCONT); 384 } 385 return; 386 } 387 } 388} 389 390#ifdef debug 391/* DEBUG */ 392pgrpdump() 393{ 394 register struct pgrp *pgrp; 395 register struct proc *p; 396 register i; 397 398 for (i=0; i<PIDHSZ; i++) { 399 if (pgrphash[i]) { 400 printf("\tindx %d\n", i); 401 for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 402 printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 403 pgrp, pgrp->pg_id, pgrp->pg_session, 404 pgrp->pg_session->s_count, pgrp->pg_mem); 405 for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 406 printf("\t\tpid %d addr %x pgrp %x\n", 407 p->p_pid, p, p->p_pgrp); 408 } 409 } 410 411 } 412 } 413} 414#endif /* debug */
|