123371Smckusick /* 263176Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 423371Smckusick * 544438Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*67732Smckusick * @(#)kern_proc.c 8.5 (Berkeley) 08/22/94 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 /* 2755402Smckusick * Structure associated with user cacheing. 2855402Smckusick */ 2955402Smckusick struct uidinfo { 30*67732Smckusick LIST_ENTRY(uidinfo) ui_hash; 3155402Smckusick uid_t ui_uid; 3255402Smckusick long ui_proccnt; 33*67732Smckusick }; 34*67732Smckusick #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 35*67732Smckusick LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 36*67732Smckusick u_long uihash; /* size of hash table - 1 */ 3755402Smckusick 3855402Smckusick /* 39*67732Smckusick * Other process lists 4055402Smckusick */ 41*67732Smckusick struct pidhashhead *pidhashtbl; 42*67732Smckusick u_long pidhash; 43*67732Smckusick struct pgrphashhead *pgrphashtbl; 44*67732Smckusick u_long pgrphash; 45*67732Smckusick struct proclist allproc; 46*67732Smckusick struct proclist zombproc; 47*67732Smckusick 48*67732Smckusick /* 49*67732Smckusick * Initialize global process hashing structures. 50*67732Smckusick */ 51*67732Smckusick procinit() 5255402Smckusick { 5355402Smckusick 54*67732Smckusick LIST_INIT(&allproc); 55*67732Smckusick LIST_INIT(&zombproc); 56*67732Smckusick pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); 57*67732Smckusick pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); 5855402Smckusick uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 5955402Smckusick } 6055402Smckusick 6155402Smckusick /* 6255402Smckusick * Change the count associated with number of processes 6355402Smckusick * a given user is using. 6455402Smckusick */ 6555402Smckusick int 6655402Smckusick chgproccnt(uid, diff) 6755402Smckusick uid_t uid; 6855402Smckusick int diff; 6955402Smckusick { 70*67732Smckusick register struct uidinfo *uip; 71*67732Smckusick register struct uihashhead *uipp; 7255402Smckusick 73*67732Smckusick uipp = UIHASH(uid); 74*67732Smckusick for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) 7555402Smckusick if (uip->ui_uid == uid) 7655402Smckusick break; 7755402Smckusick if (uip) { 7855402Smckusick uip->ui_proccnt += diff; 7955402Smckusick if (uip->ui_proccnt > 0) 8055402Smckusick return (uip->ui_proccnt); 8155402Smckusick if (uip->ui_proccnt < 0) 8255402Smckusick panic("chgproccnt: procs < 0"); 83*67732Smckusick LIST_REMOVE(uip, ui_hash); 8455402Smckusick FREE(uip, M_PROC); 8555402Smckusick return (0); 8655402Smckusick } 8755402Smckusick if (diff <= 0) { 8855402Smckusick if (diff == 0) 8955402Smckusick return(0); 9055402Smckusick panic("chgproccnt: lost user"); 9155402Smckusick } 9255402Smckusick MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 93*67732Smckusick LIST_INSERT_HEAD(uipp, uip, ui_hash); 9455402Smckusick uip->ui_uid = uid; 9555402Smckusick uip->ui_proccnt = diff; 9655402Smckusick return (diff); 9755402Smckusick } 9855402Smckusick 9955402Smckusick /* 1007497Sroot * Is p an inferior of the current process? 10136Sbill */ 1027497Sroot inferior(p) 1037816Sroot register struct proc *p; 10436Sbill { 10545673Skarels 10647542Skarels for (; p != curproc; p = p->p_pptr) 10747542Skarels if (p->p_pid == 0) 1087497Sroot return (0); 1097497Sroot return (1); 11036Sbill } 1117816Sroot 11240709Skarels /* 11340709Skarels * Locate a process by number 11440709Skarels */ 1157816Sroot struct proc * 1167816Sroot pfind(pid) 11764534Sbostic register pid_t pid; 1187816Sroot { 11964534Sbostic register struct proc *p; 1207816Sroot 121*67732Smckusick for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) 1227816Sroot if (p->p_pid == pid) 1237816Sroot return (p); 12464534Sbostic return (NULL); 1257816Sroot } 12616529Skarels 12716529Skarels /* 12835810Smarc * Locate a process group by number 12935810Smarc */ 13035810Smarc struct pgrp * 13135810Smarc pgfind(pgid) 13235810Smarc register pid_t pgid; 13335810Smarc { 13464534Sbostic register struct pgrp *pgrp; 13535810Smarc 136*67732Smckusick for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; 137*67732Smckusick pgrp = pgrp->pg_hash.le_next) 13835810Smarc if (pgrp->pg_id == pgid) 13940709Skarels return (pgrp); 14064534Sbostic return (NULL); 14135810Smarc } 14235810Smarc 14335810Smarc /* 14435810Smarc * Move p to a new or existing process group (and session) 14535810Smarc */ 14647542Skarels enterpgrp(p, pgid, mksess) 14735810Smarc register struct proc *p; 14835810Smarc pid_t pgid; 14952494Storek int mksess; 15035810Smarc { 15135810Smarc register struct pgrp *pgrp = pgfind(pgid); 15245673Skarels int n; 15335810Smarc 15439562Smarc #ifdef DIAGNOSTIC 15564534Sbostic if (pgrp != NULL && mksess) /* firewalls */ 15647542Skarels panic("enterpgrp: setsid into non-empty pgrp"); 15735810Smarc if (SESS_LEADER(p)) 15847542Skarels panic("enterpgrp: session leader attempted setpgrp"); 15939562Smarc #endif 16037589Smarc if (pgrp == NULL) { 16157055Smarc pid_t savepid = p->p_pid; 16257055Smarc struct proc *np; 16335810Smarc /* 16435810Smarc * new process group 16535810Smarc */ 16639562Smarc #ifdef DIAGNOSTIC 16735810Smarc if (p->p_pid != pgid) 16847542Skarels panic("enterpgrp: new pgrp and pid != pgid"); 16939562Smarc #endif 17035810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 171*67732Smckusick M_WAITOK); 17257055Smarc if ((np = pfind(savepid)) == NULL || np != p) 17357055Smarc return (ESRCH); 17435810Smarc if (mksess) { 17535810Smarc register struct session *sess; 17650252Skarels 17735810Smarc /* 17835810Smarc * new session 17935810Smarc */ 18035810Smarc MALLOC(sess, struct session *, sizeof(struct session), 181*67732Smckusick M_SESSION, M_WAITOK); 18235810Smarc sess->s_leader = p; 18335810Smarc sess->s_count = 1; 18439562Smarc sess->s_ttyvp = NULL; 18539562Smarc sess->s_ttyp = NULL; 18650252Skarels bcopy(p->p_session->s_login, sess->s_login, 18750252Skarels sizeof(sess->s_login)); 18864589Sbostic p->p_flag &= ~P_CONTROLT; 18935810Smarc pgrp->pg_session = sess; 19039562Smarc #ifdef DIAGNOSTIC 19147542Skarels if (p != curproc) 19247542Skarels panic("enterpgrp: mksession and p != curproc"); 19339562Smarc #endif 19435810Smarc } else { 19535810Smarc pgrp->pg_session = p->p_session; 19635810Smarc pgrp->pg_session->s_count++; 19735810Smarc } 19835810Smarc pgrp->pg_id = pgid; 199*67732Smckusick LIST_INIT(&pgrp->pg_members); 200*67732Smckusick LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 20135810Smarc pgrp->pg_jobc = 0; 20244387Smarc } else if (pgrp == p->p_pgrp) 20357055Smarc return (0); 20445673Skarels 20535810Smarc /* 20645673Skarels * Adjust eligibility of affected pgrps to participate in job control. 20745673Skarels * Increment eligibility counts before decrementing, otherwise we 20845673Skarels * could reach 0 spuriously during the first call. 20935810Smarc */ 21045673Skarels fixjobc(p, pgrp, 1); 21145673Skarels fixjobc(p, p->p_pgrp, 0); 21245673Skarels 213*67732Smckusick LIST_REMOVE(p, p_pglist); 214*67732Smckusick if (p->p_pgrp->pg_members.lh_first == 0) 21545673Skarels pgdelete(p->p_pgrp); 21645673Skarels p->p_pgrp = pgrp; 217*67732Smckusick LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); 21857055Smarc return (0); 21935810Smarc } 22035810Smarc 22135810Smarc /* 22235810Smarc * remove process from process group 22335810Smarc */ 22447542Skarels leavepgrp(p) 22535810Smarc register struct proc *p; 22635810Smarc { 22735810Smarc 228*67732Smckusick LIST_REMOVE(p, p_pglist); 229*67732Smckusick if (p->p_pgrp->pg_members.lh_first == 0) 23035810Smarc pgdelete(p->p_pgrp); 23135810Smarc p->p_pgrp = 0; 23257055Smarc return (0); 23335810Smarc } 23435810Smarc 23535810Smarc /* 23635810Smarc * delete a process group 23735810Smarc */ 23835810Smarc pgdelete(pgrp) 23935810Smarc register struct pgrp *pgrp; 24035810Smarc { 24135810Smarc 24239562Smarc if (pgrp->pg_session->s_ttyp != NULL && 24339562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 24439562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 245*67732Smckusick LIST_REMOVE(pgrp, pg_hash); 24635810Smarc if (--pgrp->pg_session->s_count == 0) 24735810Smarc FREE(pgrp->pg_session, M_SESSION); 24835810Smarc FREE(pgrp, M_PGRP); 24935810Smarc } 25035810Smarc 25152494Storek static void orphanpg(); 25248417Skarels 25335810Smarc /* 25445673Skarels * Adjust pgrp jobc counters when specified process changes process group. 25545673Skarels * We count the number of processes in each process group that "qualify" 25645673Skarels * the group for terminal job control (those with a parent in a different 25745673Skarels * process group of the same session). If that count reaches zero, the 25845673Skarels * process group becomes orphaned. Check both the specified process' 25945673Skarels * process group and that of its children. 26045673Skarels * entering == 0 => p is leaving specified group. 26145673Skarels * entering == 1 => p is entering specified group. 26244387Smarc */ 26345673Skarels fixjobc(p, pgrp, entering) 26444387Smarc register struct proc *p; 26545673Skarels register struct pgrp *pgrp; 26645673Skarels int entering; 26744387Smarc { 26845673Skarels register struct pgrp *hispgrp; 26945673Skarels register struct session *mysession = pgrp->pg_session; 27044387Smarc 27145673Skarels /* 27245673Skarels * Check p's parent to see whether p qualifies its own process 27345673Skarels * group; if so, adjust count for p's process group. 27445673Skarels */ 27545673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 27644387Smarc hispgrp->pg_session == mysession) 27745673Skarels if (entering) 27845673Skarels pgrp->pg_jobc++; 27945673Skarels else if (--pgrp->pg_jobc == 0) 28045673Skarels orphanpg(pgrp); 28144387Smarc 28245673Skarels /* 28345673Skarels * Check this process' children to see whether they qualify 28445673Skarels * their process groups; if so, adjust counts for children's 28545673Skarels * process groups. 28645673Skarels */ 287*67732Smckusick for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) 28845673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 28944387Smarc hispgrp->pg_session == mysession && 29044387Smarc p->p_stat != SZOMB) 29145673Skarels if (entering) 29244387Smarc hispgrp->pg_jobc++; 29345673Skarels else if (--hispgrp->pg_jobc == 0) 29445673Skarels orphanpg(hispgrp); 29545673Skarels } 29644387Smarc 29745673Skarels /* 29845673Skarels * A process group has become orphaned; 29945673Skarels * if there are any stopped processes in the group, 30045673Skarels * hang-up all process in that group. 30145673Skarels */ 30252494Storek static void 30345673Skarels orphanpg(pg) 30445673Skarels struct pgrp *pg; 30545673Skarels { 30645673Skarels register struct proc *p; 30745673Skarels 308*67732Smckusick for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { 30945673Skarels if (p->p_stat == SSTOP) { 310*67732Smckusick for (p = pg->pg_members.lh_first; p != 0; 311*67732Smckusick p = p->p_pglist.le_next) { 31245673Skarels psignal(p, SIGHUP); 31345673Skarels psignal(p, SIGCONT); 31444387Smarc } 31545673Skarels return; 31645673Skarels } 31745673Skarels } 31844387Smarc } 31945673Skarels 320*67732Smckusick #ifdef DEBUG 32135810Smarc pgrpdump() 32235810Smarc { 32335810Smarc register struct pgrp *pgrp; 32435810Smarc register struct proc *p; 32535810Smarc register i; 32635810Smarc 327*67732Smckusick for (i = 0; i <= pgrphash; i++) { 328*67732Smckusick if (pgrp = pgrphashtbl[i].lh_first) { 329*67732Smckusick printf("\tindx %d\n", i); 330*67732Smckusick for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { 331*67732Smckusick printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 332*67732Smckusick pgrp, pgrp->pg_id, pgrp->pg_session, 333*67732Smckusick pgrp->pg_session->s_count, 334*67732Smckusick pgrp->pg_members.lh_first); 335*67732Smckusick for (p = pgrp->pg_members.lh_first; p != 0; 336*67732Smckusick p = p->p_pglist.le_next) { 337*67732Smckusick printf("\t\tpid %d addr %x pgrp %x\n", 338*67732Smckusick p->p_pid, p, p->p_pgrp); 339*67732Smckusick } 340*67732Smckusick } 34135810Smarc } 34235810Smarc } 34335810Smarc } 344*67732Smckusick #endif /* DEBUG */ 345