123371Smckusick /* 248417Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 337728Smckusick * All rights reserved. 423371Smckusick * 544438Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*52494Storek * @(#)kern_proc.c 7.19 (Berkeley) 02/14/92 823371Smckusick */ 936Sbill 1051459Sbostic #include <sys/param.h> 1151459Sbostic #include <sys/systm.h> 1251459Sbostic #include <sys/map.h> 1351459Sbostic #include <sys/kernel.h> 1451459Sbostic #include <sys/proc.h> 1551459Sbostic #include <sys/buf.h> 1651459Sbostic #include <sys/acct.h> 1751459Sbostic #include <sys/wait.h> 1851459Sbostic #include <sys/file.h> 1951459Sbostic #include <ufs/ufs/quota.h> 2051459Sbostic #include <sys/uio.h> 2151459Sbostic #include <sys/malloc.h> 2251459Sbostic #include <sys/mbuf.h> 2351459Sbostic #include <sys/ioctl.h> 2451459Sbostic #include <sys/tty.h> 2536Sbill 2617540Skarels /* 277497Sroot * Is p an inferior of the current process? 2836Sbill */ 297497Sroot inferior(p) 307816Sroot register struct proc *p; 3136Sbill { 3245673Skarels 3347542Skarels for (; p != curproc; p = p->p_pptr) 3447542Skarels if (p->p_pid == 0) 357497Sroot return (0); 367497Sroot return (1); 3736Sbill } 387816Sroot 3940709Skarels /* 4040709Skarels * Locate a process by number 4140709Skarels */ 427816Sroot struct proc * 437816Sroot pfind(pid) 4435810Smarc register pid; 457816Sroot { 4640709Skarels register struct proc *p = pidhash[PIDHASH(pid)]; 477816Sroot 4840709Skarels for (; p; p = p->p_hash) 497816Sroot if (p->p_pid == pid) 507816Sroot return (p); 517816Sroot return ((struct proc *)0); 527816Sroot } 5316529Skarels 5416529Skarels /* 5535810Smarc * Locate a process group by number 5635810Smarc */ 5735810Smarc struct pgrp * 5835810Smarc pgfind(pgid) 5935810Smarc register pid_t pgid; 6035810Smarc { 6135810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 6235810Smarc 6335810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 6435810Smarc if (pgrp->pg_id == pgid) 6540709Skarels return (pgrp); 6635810Smarc return ((struct pgrp *)0); 6735810Smarc } 6835810Smarc 6935810Smarc /* 7035810Smarc * Move p to a new or existing process group (and session) 7135810Smarc */ 7247542Skarels enterpgrp(p, pgid, mksess) 7335810Smarc register struct proc *p; 7435810Smarc pid_t pgid; 75*52494Storek int mksess; 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; 10050252Skarels 10135810Smarc /* 10235810Smarc * new session 10335810Smarc */ 10435810Smarc MALLOC(sess, struct session *, sizeof(struct session), 10535810Smarc M_SESSION, M_WAITOK); 10635810Smarc sess->s_leader = p; 10735810Smarc sess->s_count = 1; 10839562Smarc sess->s_ttyvp = NULL; 10939562Smarc sess->s_ttyp = NULL; 11050252Skarels bcopy(p->p_session->s_login, sess->s_login, 11150252Skarels sizeof(sess->s_login)); 11239562Smarc p->p_flag &= ~SCTTY; 11335810Smarc pgrp->pg_session = sess; 11439562Smarc #ifdef DIAGNOSTIC 11547542Skarels if (p != curproc) 11647542Skarels panic("enterpgrp: mksession and p != curproc"); 11739562Smarc #endif 11835810Smarc } else { 11935810Smarc pgrp->pg_session = p->p_session; 12035810Smarc pgrp->pg_session->s_count++; 12135810Smarc } 12235810Smarc pgrp->pg_id = pgid; 12345673Skarels pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 12435810Smarc pgrphash[n] = pgrp; 12535810Smarc pgrp->pg_jobc = 0; 12639562Smarc pgrp->pg_mem = NULL; 12744387Smarc } else if (pgrp == p->p_pgrp) 12844387Smarc return; 12945673Skarels 13035810Smarc /* 13145673Skarels * Adjust eligibility of affected pgrps to participate in job control. 13245673Skarels * Increment eligibility counts before decrementing, otherwise we 13345673Skarels * could reach 0 spuriously during the first call. 13435810Smarc */ 13545673Skarels fixjobc(p, pgrp, 1); 13645673Skarels fixjobc(p, p->p_pgrp, 0); 13745673Skarels 13835810Smarc /* 13935810Smarc * unlink p from old process group 14035810Smarc */ 14145673Skarels for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) 14235810Smarc if (*pp == p) { 14335810Smarc *pp = p->p_pgrpnxt; 14435810Smarc goto done; 14535810Smarc } 14647542Skarels panic("enterpgrp: can't find p on old pgrp"); 14735810Smarc done: 14835810Smarc /* 14945673Skarels * delete old if empty 15045673Skarels */ 15145673Skarels if (p->p_pgrp->pg_mem == 0) 15245673Skarels pgdelete(p->p_pgrp); 15345673Skarels /* 15435810Smarc * link into new one 15535810Smarc */ 15645673Skarels p->p_pgrp = pgrp; 15735810Smarc p->p_pgrpnxt = pgrp->pg_mem; 15835810Smarc pgrp->pg_mem = p; 15935810Smarc } 16035810Smarc 16135810Smarc /* 16235810Smarc * remove process from process group 16335810Smarc */ 16447542Skarels leavepgrp(p) 16535810Smarc register struct proc *p; 16635810Smarc { 16735810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 16835810Smarc 16935810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 17035810Smarc if (*pp == p) { 17135810Smarc *pp = p->p_pgrpnxt; 17235810Smarc goto done; 17335810Smarc } 17447542Skarels panic("leavepgrp: can't find p in pgrp"); 17535810Smarc done: 17635810Smarc if (!p->p_pgrp->pg_mem) 17735810Smarc pgdelete(p->p_pgrp); 17835810Smarc p->p_pgrp = 0; 17935810Smarc } 18035810Smarc 18135810Smarc /* 18235810Smarc * delete a process group 18335810Smarc */ 18435810Smarc pgdelete(pgrp) 18535810Smarc register struct pgrp *pgrp; 18635810Smarc { 18735810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 18835810Smarc 18939562Smarc if (pgrp->pg_session->s_ttyp != NULL && 19039562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 19139562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 19235810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 19335810Smarc if (*pgp == pgrp) { 19435810Smarc *pgp = pgrp->pg_hforw; 19535810Smarc goto done; 19635810Smarc } 19737589Smarc panic("pgdelete: can't find pgrp on hash chain"); 19835810Smarc done: 19935810Smarc if (--pgrp->pg_session->s_count == 0) 20035810Smarc FREE(pgrp->pg_session, M_SESSION); 20135810Smarc FREE(pgrp, M_PGRP); 20235810Smarc } 20335810Smarc 204*52494Storek static void orphanpg(); 20548417Skarels 20635810Smarc /* 20745673Skarels * Adjust pgrp jobc counters when specified process changes process group. 20845673Skarels * We count the number of processes in each process group that "qualify" 20945673Skarels * the group for terminal job control (those with a parent in a different 21045673Skarels * process group of the same session). If that count reaches zero, the 21145673Skarels * process group becomes orphaned. Check both the specified process' 21245673Skarels * process group and that of its children. 21345673Skarels * entering == 0 => p is leaving specified group. 21445673Skarels * entering == 1 => p is entering specified group. 21544387Smarc */ 21645673Skarels fixjobc(p, pgrp, entering) 21744387Smarc register struct proc *p; 21845673Skarels register struct pgrp *pgrp; 21945673Skarels int entering; 22044387Smarc { 22145673Skarels register struct pgrp *hispgrp; 22245673Skarels register struct session *mysession = pgrp->pg_session; 22344387Smarc 22445673Skarels /* 22545673Skarels * Check p's parent to see whether p qualifies its own process 22645673Skarels * group; if so, adjust count for p's process group. 22745673Skarels */ 22845673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 22944387Smarc hispgrp->pg_session == mysession) 23045673Skarels if (entering) 23145673Skarels pgrp->pg_jobc++; 23245673Skarels else if (--pgrp->pg_jobc == 0) 23345673Skarels orphanpg(pgrp); 23444387Smarc 23545673Skarels /* 23645673Skarels * Check this process' children to see whether they qualify 23745673Skarels * their process groups; if so, adjust counts for children's 23845673Skarels * process groups. 23945673Skarels */ 24045673Skarels for (p = p->p_cptr; p; p = p->p_osptr) 24145673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 24244387Smarc hispgrp->pg_session == mysession && 24344387Smarc p->p_stat != SZOMB) 24445673Skarels if (entering) 24544387Smarc hispgrp->pg_jobc++; 24645673Skarels else if (--hispgrp->pg_jobc == 0) 24745673Skarels orphanpg(hispgrp); 24845673Skarels } 24944387Smarc 25045673Skarels /* 25145673Skarels * A process group has become orphaned; 25245673Skarels * if there are any stopped processes in the group, 25345673Skarels * hang-up all process in that group. 25445673Skarels */ 255*52494Storek static void 25645673Skarels orphanpg(pg) 25745673Skarels struct pgrp *pg; 25845673Skarels { 25945673Skarels register struct proc *p; 26045673Skarels 26145673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 26245673Skarels if (p->p_stat == SSTOP) { 26345673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 26445673Skarels psignal(p, SIGHUP); 26545673Skarels psignal(p, SIGCONT); 26644387Smarc } 26745673Skarels return; 26845673Skarels } 26945673Skarels } 27044387Smarc } 27145673Skarels 27237728Smckusick #ifdef debug 27335810Smarc /* DEBUG */ 27435810Smarc pgrpdump() 27535810Smarc { 27635810Smarc register struct pgrp *pgrp; 27735810Smarc register struct proc *p; 27835810Smarc register i; 27935810Smarc 28035810Smarc for (i=0; i<PIDHSZ; i++) { 28135810Smarc if (pgrphash[i]) { 28235810Smarc printf("\tindx %d\n", i); 28335810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 28435810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 28535810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 28635810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 28735810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 28835810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 28935810Smarc p->p_pid, p, p->p_pgrp); 29035810Smarc } 29135810Smarc } 29235810Smarc 29335810Smarc } 29435810Smarc } 29535810Smarc } 29637728Smckusick #endif /* debug */ 297