123371Smckusick /* 2*48417Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 337728Smckusick * All rights reserved. 423371Smckusick * 544438Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*48417Skarels * @(#)kern_proc.c 7.15 (Berkeley) 04/20/91 823371Smckusick */ 936Sbill 1017091Sbloom #include "param.h" 1117091Sbloom #include "systm.h" 1217091Sbloom #include "map.h" 1317091Sbloom #include "kernel.h" 1417091Sbloom #include "proc.h" 1517091Sbloom #include "buf.h" 1617091Sbloom #include "seg.h" 1717091Sbloom #include "acct.h" 1817091Sbloom #include "wait.h" 1917091Sbloom #include "file.h" 2037728Smckusick #include "../ufs/quota.h" 2117091Sbloom #include "uio.h" 2235810Smarc #include "malloc.h" 2317091Sbloom #include "mbuf.h" 2439064Smarc #include "ioctl.h" 2535810Smarc #include "tty.h" 2636Sbill 2717540Skarels /* 287497Sroot * Is p an inferior of the current process? 2936Sbill */ 307497Sroot inferior(p) 317816Sroot register struct proc *p; 3236Sbill { 3345673Skarels 3447542Skarels for (; p != curproc; p = p->p_pptr) 3547542Skarels if (p->p_pid == 0) 367497Sroot return (0); 377497Sroot return (1); 3836Sbill } 397816Sroot 4040709Skarels /* 4140709Skarels * Locate a process by number 4240709Skarels */ 437816Sroot struct proc * 447816Sroot pfind(pid) 4535810Smarc register pid; 467816Sroot { 4740709Skarels register struct proc *p = pidhash[PIDHASH(pid)]; 487816Sroot 4940709Skarels for (; p; p = p->p_hash) 507816Sroot if (p->p_pid == pid) 517816Sroot return (p); 527816Sroot return ((struct proc *)0); 537816Sroot } 5416529Skarels 5516529Skarels /* 5635810Smarc * Locate a process group by number 5735810Smarc */ 5835810Smarc struct pgrp * 5935810Smarc pgfind(pgid) 6035810Smarc register pid_t pgid; 6135810Smarc { 6235810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 6335810Smarc 6435810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 6535810Smarc if (pgrp->pg_id == pgid) 6640709Skarels return (pgrp); 6735810Smarc return ((struct pgrp *)0); 6835810Smarc } 6935810Smarc 7035810Smarc /* 7135810Smarc * Move p to a new or existing process group (and session) 7235810Smarc */ 7347542Skarels enterpgrp(p, pgid, mksess) 7435810Smarc register struct proc *p; 7535810Smarc pid_t pgid; 7635810Smarc { 7735810Smarc register struct pgrp *pgrp = pgfind(pgid); 7845673Skarels register struct proc **pp; 7935810Smarc register struct proc *cp; 8045673Skarels int n; 8135810Smarc 8239562Smarc #ifdef DIAGNOSTIC 8335810Smarc if (pgrp && mksess) /* firewalls */ 8447542Skarels panic("enterpgrp: setsid into non-empty pgrp"); 8535810Smarc if (SESS_LEADER(p)) 8647542Skarels panic("enterpgrp: session leader attempted setpgrp"); 8739562Smarc #endif 8837589Smarc if (pgrp == NULL) { 8935810Smarc /* 9035810Smarc * new process group 9135810Smarc */ 9239562Smarc #ifdef DIAGNOSTIC 9335810Smarc if (p->p_pid != pgid) 9447542Skarels panic("enterpgrp: new pgrp and pid != pgid"); 9539562Smarc #endif 9635810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 9735810Smarc M_WAITOK); 9835810Smarc if (mksess) { 9935810Smarc register struct session *sess; 10035810Smarc /* 10135810Smarc * new session 10235810Smarc */ 10335810Smarc MALLOC(sess, struct session *, sizeof(struct session), 10435810Smarc M_SESSION, M_WAITOK); 10535810Smarc sess->s_leader = p; 10635810Smarc sess->s_count = 1; 10739562Smarc sess->s_ttyvp = NULL; 10839562Smarc sess->s_ttyp = NULL; 10939562Smarc p->p_flag &= ~SCTTY; 11035810Smarc pgrp->pg_session = sess; 11139562Smarc #ifdef DIAGNOSTIC 11247542Skarels if (p != curproc) 11347542Skarels panic("enterpgrp: mksession and p != curproc"); 11439562Smarc #endif 11535810Smarc } else { 11635810Smarc pgrp->pg_session = p->p_session; 11735810Smarc pgrp->pg_session->s_count++; 11835810Smarc } 11935810Smarc pgrp->pg_id = pgid; 12045673Skarels pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 12135810Smarc pgrphash[n] = pgrp; 12235810Smarc pgrp->pg_jobc = 0; 12339562Smarc pgrp->pg_mem = NULL; 12444387Smarc } else if (pgrp == p->p_pgrp) 12544387Smarc return; 12645673Skarels 12735810Smarc /* 12845673Skarels * Adjust eligibility of affected pgrps to participate in job control. 12945673Skarels * Increment eligibility counts before decrementing, otherwise we 13045673Skarels * could reach 0 spuriously during the first call. 13135810Smarc */ 13245673Skarels fixjobc(p, pgrp, 1); 13345673Skarels fixjobc(p, p->p_pgrp, 0); 13445673Skarels 13535810Smarc /* 13635810Smarc * unlink p from old process group 13735810Smarc */ 13845673Skarels for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) 13935810Smarc if (*pp == p) { 14035810Smarc *pp = p->p_pgrpnxt; 14135810Smarc goto done; 14235810Smarc } 14347542Skarels panic("enterpgrp: can't find p on old pgrp"); 14435810Smarc done: 14535810Smarc /* 14645673Skarels * delete old if empty 14745673Skarels */ 14845673Skarels if (p->p_pgrp->pg_mem == 0) 14945673Skarels pgdelete(p->p_pgrp); 15045673Skarels /* 15135810Smarc * link into new one 15235810Smarc */ 15345673Skarels p->p_pgrp = pgrp; 15435810Smarc p->p_pgrpnxt = pgrp->pg_mem; 15535810Smarc pgrp->pg_mem = p; 15635810Smarc } 15735810Smarc 15835810Smarc /* 15935810Smarc * remove process from process group 16035810Smarc */ 16147542Skarels leavepgrp(p) 16235810Smarc register struct proc *p; 16335810Smarc { 16435810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 16535810Smarc 16635810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 16735810Smarc if (*pp == p) { 16835810Smarc *pp = p->p_pgrpnxt; 16935810Smarc goto done; 17035810Smarc } 17147542Skarels panic("leavepgrp: can't find p in pgrp"); 17235810Smarc done: 17335810Smarc if (!p->p_pgrp->pg_mem) 17435810Smarc pgdelete(p->p_pgrp); 17535810Smarc p->p_pgrp = 0; 17635810Smarc } 17735810Smarc 17835810Smarc /* 17935810Smarc * delete a process group 18035810Smarc */ 18135810Smarc pgdelete(pgrp) 18235810Smarc register struct pgrp *pgrp; 18335810Smarc { 18435810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 18535810Smarc 18639562Smarc if (pgrp->pg_session->s_ttyp != NULL && 18739562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 18839562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 18935810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 19035810Smarc if (*pgp == pgrp) { 19135810Smarc *pgp = pgrp->pg_hforw; 19235810Smarc goto done; 19335810Smarc } 19437589Smarc panic("pgdelete: can't find pgrp on hash chain"); 19535810Smarc done: 19635810Smarc if (--pgrp->pg_session->s_count == 0) 19735810Smarc FREE(pgrp->pg_session, M_SESSION); 19835810Smarc FREE(pgrp, M_PGRP); 19935810Smarc } 20035810Smarc 201*48417Skarels static orphanpg(); 202*48417Skarels 20335810Smarc /* 20445673Skarels * Adjust pgrp jobc counters when specified process changes process group. 20545673Skarels * We count the number of processes in each process group that "qualify" 20645673Skarels * the group for terminal job control (those with a parent in a different 20745673Skarels * process group of the same session). If that count reaches zero, the 20845673Skarels * process group becomes orphaned. Check both the specified process' 20945673Skarels * process group and that of its children. 21045673Skarels * entering == 0 => p is leaving specified group. 21145673Skarels * entering == 1 => p is entering specified group. 21244387Smarc */ 21345673Skarels fixjobc(p, pgrp, entering) 21444387Smarc register struct proc *p; 21545673Skarels register struct pgrp *pgrp; 21645673Skarels int entering; 21744387Smarc { 21845673Skarels register struct pgrp *hispgrp; 21945673Skarels register struct session *mysession = pgrp->pg_session; 22044387Smarc 22145673Skarels /* 22245673Skarels * Check p's parent to see whether p qualifies its own process 22345673Skarels * group; if so, adjust count for p's process group. 22445673Skarels */ 22545673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 22644387Smarc hispgrp->pg_session == mysession) 22745673Skarels if (entering) 22845673Skarels pgrp->pg_jobc++; 22945673Skarels else if (--pgrp->pg_jobc == 0) 23045673Skarels orphanpg(pgrp); 23144387Smarc 23245673Skarels /* 23345673Skarels * Check this process' children to see whether they qualify 23445673Skarels * their process groups; if so, adjust counts for children's 23545673Skarels * process groups. 23645673Skarels */ 23745673Skarels for (p = p->p_cptr; p; p = p->p_osptr) 23845673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 23944387Smarc hispgrp->pg_session == mysession && 24044387Smarc p->p_stat != SZOMB) 24145673Skarels if (entering) 24244387Smarc hispgrp->pg_jobc++; 24345673Skarels else if (--hispgrp->pg_jobc == 0) 24445673Skarels orphanpg(hispgrp); 24545673Skarels } 24644387Smarc 24745673Skarels /* 24845673Skarels * A process group has become orphaned; 24945673Skarels * if there are any stopped processes in the group, 25045673Skarels * hang-up all process in that group. 25145673Skarels */ 25245673Skarels static 25345673Skarels orphanpg(pg) 25445673Skarels struct pgrp *pg; 25545673Skarels { 25645673Skarels register struct proc *p; 25745673Skarels 25845673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 25945673Skarels if (p->p_stat == SSTOP) { 26045673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 26145673Skarels psignal(p, SIGHUP); 26245673Skarels psignal(p, SIGCONT); 26344387Smarc } 26445673Skarels return; 26545673Skarels } 26645673Skarels } 26744387Smarc } 26845673Skarels 26937728Smckusick #ifdef debug 27035810Smarc /* DEBUG */ 27135810Smarc pgrpdump() 27235810Smarc { 27335810Smarc register struct pgrp *pgrp; 27435810Smarc register struct proc *p; 27535810Smarc register i; 27635810Smarc 27735810Smarc for (i=0; i<PIDHSZ; i++) { 27835810Smarc if (pgrphash[i]) { 27935810Smarc printf("\tindx %d\n", i); 28035810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 28135810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 28235810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 28335810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 28435810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 28535810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 28635810Smarc p->p_pid, p, p->p_pgrp); 28735810Smarc } 28835810Smarc } 28935810Smarc 29035810Smarc } 29135810Smarc } 29235810Smarc } 29337728Smckusick #endif /* debug */ 294