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*50252Skarels * @(#)kern_proc.c 7.16 (Berkeley) 06/28/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; 100*50252Skarels 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; 110*50252Skarels bcopy(p->p_session->s_login, sess->s_login, 111*50252Skarels 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 20448417Skarels static 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 */ 25545673Skarels static 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