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*55402Smckusick * @(#)kern_proc.c 7.20 (Berkeley) 07/19/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 /* 27*55402Smckusick * Structure associated with user cacheing. 28*55402Smckusick */ 29*55402Smckusick struct uidinfo { 30*55402Smckusick struct uidinfo *ui_next; 31*55402Smckusick struct uidinfo **ui_prev; 32*55402Smckusick uid_t ui_uid; 33*55402Smckusick long ui_proccnt; 34*55402Smckusick } **uihashtbl; 35*55402Smckusick u_long uihash; /* size of hash table - 1 */ 36*55402Smckusick #define UIHASH(uid) ((uid) & uihash) 37*55402Smckusick 38*55402Smckusick /* 39*55402Smckusick * Allocate a hash table. 40*55402Smckusick */ 41*55402Smckusick usrinfoinit() 42*55402Smckusick { 43*55402Smckusick 44*55402Smckusick uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 45*55402Smckusick } 46*55402Smckusick 47*55402Smckusick /* 48*55402Smckusick * Change the count associated with number of processes 49*55402Smckusick * a given user is using. 50*55402Smckusick */ 51*55402Smckusick int 52*55402Smckusick chgproccnt(uid, diff) 53*55402Smckusick uid_t uid; 54*55402Smckusick int diff; 55*55402Smckusick { 56*55402Smckusick register struct uidinfo **uipp, *uip, *uiq; 57*55402Smckusick 58*55402Smckusick uipp = &uihashtbl[UIHASH(uid)]; 59*55402Smckusick for (uip = *uipp; uip; uip = uip->ui_next) 60*55402Smckusick if (uip->ui_uid == uid) 61*55402Smckusick break; 62*55402Smckusick if (uip) { 63*55402Smckusick uip->ui_proccnt += diff; 64*55402Smckusick if (uip->ui_proccnt > 0) 65*55402Smckusick return (uip->ui_proccnt); 66*55402Smckusick if (uip->ui_proccnt < 0) 67*55402Smckusick panic("chgproccnt: procs < 0"); 68*55402Smckusick if (uiq = uip->ui_next) 69*55402Smckusick uiq->ui_prev = uip->ui_prev; 70*55402Smckusick *uip->ui_prev = uiq; 71*55402Smckusick FREE(uip, M_PROC); 72*55402Smckusick return (0); 73*55402Smckusick } 74*55402Smckusick if (diff <= 0) { 75*55402Smckusick if (diff == 0) 76*55402Smckusick return(0); 77*55402Smckusick panic("chgproccnt: lost user"); 78*55402Smckusick } 79*55402Smckusick MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 80*55402Smckusick if (uiq = *uipp) 81*55402Smckusick uiq->ui_prev = &uip->ui_next; 82*55402Smckusick uip->ui_next = uiq; 83*55402Smckusick uip->ui_prev = uipp; 84*55402Smckusick *uipp = uip; 85*55402Smckusick uip->ui_uid = uid; 86*55402Smckusick uip->ui_proccnt = diff; 87*55402Smckusick return (diff); 88*55402Smckusick } 89*55402Smckusick 90*55402Smckusick /* 917497Sroot * Is p an inferior of the current process? 9236Sbill */ 937497Sroot inferior(p) 947816Sroot register struct proc *p; 9536Sbill { 9645673Skarels 9747542Skarels for (; p != curproc; p = p->p_pptr) 9847542Skarels if (p->p_pid == 0) 997497Sroot return (0); 1007497Sroot return (1); 10136Sbill } 1027816Sroot 10340709Skarels /* 10440709Skarels * Locate a process by number 10540709Skarels */ 1067816Sroot struct proc * 1077816Sroot pfind(pid) 10835810Smarc register pid; 1097816Sroot { 11040709Skarels register struct proc *p = pidhash[PIDHASH(pid)]; 1117816Sroot 11240709Skarels for (; p; p = p->p_hash) 1137816Sroot if (p->p_pid == pid) 1147816Sroot return (p); 1157816Sroot return ((struct proc *)0); 1167816Sroot } 11716529Skarels 11816529Skarels /* 11935810Smarc * Locate a process group by number 12035810Smarc */ 12135810Smarc struct pgrp * 12235810Smarc pgfind(pgid) 12335810Smarc register pid_t pgid; 12435810Smarc { 12535810Smarc register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)]; 12635810Smarc 12735810Smarc for (; pgrp; pgrp = pgrp->pg_hforw) 12835810Smarc if (pgrp->pg_id == pgid) 12940709Skarels return (pgrp); 13035810Smarc return ((struct pgrp *)0); 13135810Smarc } 13235810Smarc 13335810Smarc /* 13435810Smarc * Move p to a new or existing process group (and session) 13535810Smarc */ 13647542Skarels enterpgrp(p, pgid, mksess) 13735810Smarc register struct proc *p; 13835810Smarc pid_t pgid; 13952494Storek int mksess; 14035810Smarc { 14135810Smarc register struct pgrp *pgrp = pgfind(pgid); 14245673Skarels register struct proc **pp; 14335810Smarc register struct proc *cp; 14445673Skarels int n; 14535810Smarc 14639562Smarc #ifdef DIAGNOSTIC 14735810Smarc if (pgrp && mksess) /* firewalls */ 14847542Skarels panic("enterpgrp: setsid into non-empty pgrp"); 14935810Smarc if (SESS_LEADER(p)) 15047542Skarels panic("enterpgrp: session leader attempted setpgrp"); 15139562Smarc #endif 15237589Smarc if (pgrp == NULL) { 15335810Smarc /* 15435810Smarc * new process group 15535810Smarc */ 15639562Smarc #ifdef DIAGNOSTIC 15735810Smarc if (p->p_pid != pgid) 15847542Skarels panic("enterpgrp: new pgrp and pid != pgid"); 15939562Smarc #endif 16035810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 16135810Smarc M_WAITOK); 16235810Smarc if (mksess) { 16335810Smarc register struct session *sess; 16450252Skarels 16535810Smarc /* 16635810Smarc * new session 16735810Smarc */ 16835810Smarc MALLOC(sess, struct session *, sizeof(struct session), 16935810Smarc M_SESSION, M_WAITOK); 17035810Smarc sess->s_leader = p; 17135810Smarc sess->s_count = 1; 17239562Smarc sess->s_ttyvp = NULL; 17339562Smarc sess->s_ttyp = NULL; 17450252Skarels bcopy(p->p_session->s_login, sess->s_login, 17550252Skarels sizeof(sess->s_login)); 17639562Smarc p->p_flag &= ~SCTTY; 17735810Smarc pgrp->pg_session = sess; 17839562Smarc #ifdef DIAGNOSTIC 17947542Skarels if (p != curproc) 18047542Skarels panic("enterpgrp: mksession and p != curproc"); 18139562Smarc #endif 18235810Smarc } else { 18335810Smarc pgrp->pg_session = p->p_session; 18435810Smarc pgrp->pg_session->s_count++; 18535810Smarc } 18635810Smarc pgrp->pg_id = pgid; 18745673Skarels pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 18835810Smarc pgrphash[n] = pgrp; 18935810Smarc pgrp->pg_jobc = 0; 19039562Smarc pgrp->pg_mem = NULL; 19144387Smarc } else if (pgrp == p->p_pgrp) 19244387Smarc return; 19345673Skarels 19435810Smarc /* 19545673Skarels * Adjust eligibility of affected pgrps to participate in job control. 19645673Skarels * Increment eligibility counts before decrementing, otherwise we 19745673Skarels * could reach 0 spuriously during the first call. 19835810Smarc */ 19945673Skarels fixjobc(p, pgrp, 1); 20045673Skarels fixjobc(p, p->p_pgrp, 0); 20145673Skarels 20235810Smarc /* 20335810Smarc * unlink p from old process group 20435810Smarc */ 20545673Skarels for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) 20635810Smarc if (*pp == p) { 20735810Smarc *pp = p->p_pgrpnxt; 20835810Smarc goto done; 20935810Smarc } 21047542Skarels panic("enterpgrp: can't find p on old pgrp"); 21135810Smarc done: 21235810Smarc /* 21345673Skarels * delete old if empty 21445673Skarels */ 21545673Skarels if (p->p_pgrp->pg_mem == 0) 21645673Skarels pgdelete(p->p_pgrp); 21745673Skarels /* 21835810Smarc * link into new one 21935810Smarc */ 22045673Skarels p->p_pgrp = pgrp; 22135810Smarc p->p_pgrpnxt = pgrp->pg_mem; 22235810Smarc pgrp->pg_mem = p; 22335810Smarc } 22435810Smarc 22535810Smarc /* 22635810Smarc * remove process from process group 22735810Smarc */ 22847542Skarels leavepgrp(p) 22935810Smarc register struct proc *p; 23035810Smarc { 23135810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 23235810Smarc 23335810Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) 23435810Smarc if (*pp == p) { 23535810Smarc *pp = p->p_pgrpnxt; 23635810Smarc goto done; 23735810Smarc } 23847542Skarels panic("leavepgrp: can't find p in pgrp"); 23935810Smarc done: 24035810Smarc if (!p->p_pgrp->pg_mem) 24135810Smarc pgdelete(p->p_pgrp); 24235810Smarc p->p_pgrp = 0; 24335810Smarc } 24435810Smarc 24535810Smarc /* 24635810Smarc * delete a process group 24735810Smarc */ 24835810Smarc pgdelete(pgrp) 24935810Smarc register struct pgrp *pgrp; 25035810Smarc { 25135810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 25235810Smarc 25339562Smarc if (pgrp->pg_session->s_ttyp != NULL && 25439562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 25539562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 25635810Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) 25735810Smarc if (*pgp == pgrp) { 25835810Smarc *pgp = pgrp->pg_hforw; 25935810Smarc goto done; 26035810Smarc } 26137589Smarc panic("pgdelete: can't find pgrp on hash chain"); 26235810Smarc done: 26335810Smarc if (--pgrp->pg_session->s_count == 0) 26435810Smarc FREE(pgrp->pg_session, M_SESSION); 26535810Smarc FREE(pgrp, M_PGRP); 26635810Smarc } 26735810Smarc 26852494Storek static void orphanpg(); 26948417Skarels 27035810Smarc /* 27145673Skarels * Adjust pgrp jobc counters when specified process changes process group. 27245673Skarels * We count the number of processes in each process group that "qualify" 27345673Skarels * the group for terminal job control (those with a parent in a different 27445673Skarels * process group of the same session). If that count reaches zero, the 27545673Skarels * process group becomes orphaned. Check both the specified process' 27645673Skarels * process group and that of its children. 27745673Skarels * entering == 0 => p is leaving specified group. 27845673Skarels * entering == 1 => p is entering specified group. 27944387Smarc */ 28045673Skarels fixjobc(p, pgrp, entering) 28144387Smarc register struct proc *p; 28245673Skarels register struct pgrp *pgrp; 28345673Skarels int entering; 28444387Smarc { 28545673Skarels register struct pgrp *hispgrp; 28645673Skarels register struct session *mysession = pgrp->pg_session; 28744387Smarc 28845673Skarels /* 28945673Skarels * Check p's parent to see whether p qualifies its own process 29045673Skarels * group; if so, adjust count for p's process group. 29145673Skarels */ 29245673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 29344387Smarc hispgrp->pg_session == mysession) 29445673Skarels if (entering) 29545673Skarels pgrp->pg_jobc++; 29645673Skarels else if (--pgrp->pg_jobc == 0) 29745673Skarels orphanpg(pgrp); 29844387Smarc 29945673Skarels /* 30045673Skarels * Check this process' children to see whether they qualify 30145673Skarels * their process groups; if so, adjust counts for children's 30245673Skarels * process groups. 30345673Skarels */ 30445673Skarels for (p = p->p_cptr; p; p = p->p_osptr) 30545673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 30644387Smarc hispgrp->pg_session == mysession && 30744387Smarc p->p_stat != SZOMB) 30845673Skarels if (entering) 30944387Smarc hispgrp->pg_jobc++; 31045673Skarels else if (--hispgrp->pg_jobc == 0) 31145673Skarels orphanpg(hispgrp); 31245673Skarels } 31344387Smarc 31445673Skarels /* 31545673Skarels * A process group has become orphaned; 31645673Skarels * if there are any stopped processes in the group, 31745673Skarels * hang-up all process in that group. 31845673Skarels */ 31952494Storek static void 32045673Skarels orphanpg(pg) 32145673Skarels struct pgrp *pg; 32245673Skarels { 32345673Skarels register struct proc *p; 32445673Skarels 32545673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 32645673Skarels if (p->p_stat == SSTOP) { 32745673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 32845673Skarels psignal(p, SIGHUP); 32945673Skarels psignal(p, SIGCONT); 33044387Smarc } 33145673Skarels return; 33245673Skarels } 33345673Skarels } 33444387Smarc } 33545673Skarels 33637728Smckusick #ifdef debug 33735810Smarc /* DEBUG */ 33835810Smarc pgrpdump() 33935810Smarc { 34035810Smarc register struct pgrp *pgrp; 34135810Smarc register struct proc *p; 34235810Smarc register i; 34335810Smarc 34435810Smarc for (i=0; i<PIDHSZ; i++) { 34535810Smarc if (pgrphash[i]) { 34635810Smarc printf("\tindx %d\n", i); 34735810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 34835810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 34935810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 35035810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 35135810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 35235810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 35335810Smarc p->p_pid, p, p->p_pgrp); 35435810Smarc } 35535810Smarc } 35635810Smarc 35735810Smarc } 35835810Smarc } 35935810Smarc } 36037728Smckusick #endif /* debug */ 361