123371Smckusick /* 2*63176Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1993 3*63176Sbostic * The Regents of the University of California. All rights reserved. 423371Smckusick * 544438Sbostic * %sccs.include.redist.c% 637728Smckusick * 7*63176Sbostic * @(#)kern_proc.c 8.1 (Berkeley) 06/10/93 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 { 3055402Smckusick struct uidinfo *ui_next; 3155402Smckusick struct uidinfo **ui_prev; 3255402Smckusick uid_t ui_uid; 3355402Smckusick long ui_proccnt; 3455402Smckusick } **uihashtbl; 3555402Smckusick u_long uihash; /* size of hash table - 1 */ 3655402Smckusick #define UIHASH(uid) ((uid) & uihash) 3755402Smckusick 3855402Smckusick /* 3955402Smckusick * Allocate a hash table. 4055402Smckusick */ 4155402Smckusick usrinfoinit() 4255402Smckusick { 4355402Smckusick 4455402Smckusick uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 4555402Smckusick } 4655402Smckusick 4755402Smckusick /* 4855402Smckusick * Change the count associated with number of processes 4955402Smckusick * a given user is using. 5055402Smckusick */ 5155402Smckusick int 5255402Smckusick chgproccnt(uid, diff) 5355402Smckusick uid_t uid; 5455402Smckusick int diff; 5555402Smckusick { 5655402Smckusick register struct uidinfo **uipp, *uip, *uiq; 5755402Smckusick 5855402Smckusick uipp = &uihashtbl[UIHASH(uid)]; 5955402Smckusick for (uip = *uipp; uip; uip = uip->ui_next) 6055402Smckusick if (uip->ui_uid == uid) 6155402Smckusick break; 6255402Smckusick if (uip) { 6355402Smckusick uip->ui_proccnt += diff; 6455402Smckusick if (uip->ui_proccnt > 0) 6555402Smckusick return (uip->ui_proccnt); 6655402Smckusick if (uip->ui_proccnt < 0) 6755402Smckusick panic("chgproccnt: procs < 0"); 6855402Smckusick if (uiq = uip->ui_next) 6955402Smckusick uiq->ui_prev = uip->ui_prev; 7055402Smckusick *uip->ui_prev = uiq; 7155402Smckusick FREE(uip, M_PROC); 7255402Smckusick return (0); 7355402Smckusick } 7455402Smckusick if (diff <= 0) { 7555402Smckusick if (diff == 0) 7655402Smckusick return(0); 7755402Smckusick panic("chgproccnt: lost user"); 7855402Smckusick } 7955402Smckusick MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 8055402Smckusick if (uiq = *uipp) 8155402Smckusick uiq->ui_prev = &uip->ui_next; 8255402Smckusick uip->ui_next = uiq; 8355402Smckusick uip->ui_prev = uipp; 8455402Smckusick *uipp = uip; 8555402Smckusick uip->ui_uid = uid; 8655402Smckusick uip->ui_proccnt = diff; 8755402Smckusick return (diff); 8855402Smckusick } 8955402Smckusick 9055402Smckusick /* 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) { 15357055Smarc pid_t savepid = p->p_pid; 15457055Smarc struct proc *np; 15535810Smarc /* 15635810Smarc * new process group 15735810Smarc */ 15839562Smarc #ifdef DIAGNOSTIC 15935810Smarc if (p->p_pid != pgid) 16047542Skarels panic("enterpgrp: new pgrp and pid != pgid"); 16139562Smarc #endif 16235810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 16335810Smarc M_WAITOK); 16457055Smarc if ((np = pfind(savepid)) == NULL || np != p) 16557055Smarc return (ESRCH); 16635810Smarc if (mksess) { 16735810Smarc register struct session *sess; 16850252Skarels 16935810Smarc /* 17035810Smarc * new session 17135810Smarc */ 17235810Smarc MALLOC(sess, struct session *, sizeof(struct session), 17335810Smarc M_SESSION, M_WAITOK); 17435810Smarc sess->s_leader = p; 17535810Smarc sess->s_count = 1; 17639562Smarc sess->s_ttyvp = NULL; 17739562Smarc sess->s_ttyp = NULL; 17850252Skarels bcopy(p->p_session->s_login, sess->s_login, 17950252Skarels sizeof(sess->s_login)); 18039562Smarc p->p_flag &= ~SCTTY; 18135810Smarc pgrp->pg_session = sess; 18239562Smarc #ifdef DIAGNOSTIC 18347542Skarels if (p != curproc) 18447542Skarels panic("enterpgrp: mksession and p != curproc"); 18539562Smarc #endif 18635810Smarc } else { 18735810Smarc pgrp->pg_session = p->p_session; 18835810Smarc pgrp->pg_session->s_count++; 18935810Smarc } 19035810Smarc pgrp->pg_id = pgid; 19145673Skarels pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 19235810Smarc pgrphash[n] = pgrp; 19335810Smarc pgrp->pg_jobc = 0; 19439562Smarc pgrp->pg_mem = NULL; 19544387Smarc } else if (pgrp == p->p_pgrp) 19657055Smarc return (0); 19745673Skarels 19835810Smarc /* 19945673Skarels * Adjust eligibility of affected pgrps to participate in job control. 20045673Skarels * Increment eligibility counts before decrementing, otherwise we 20145673Skarels * could reach 0 spuriously during the first call. 20235810Smarc */ 20345673Skarels fixjobc(p, pgrp, 1); 20445673Skarels fixjobc(p, p->p_pgrp, 0); 20545673Skarels 20635810Smarc /* 20735810Smarc * unlink p from old process group 20835810Smarc */ 20957055Smarc for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 21035810Smarc if (*pp == p) { 21135810Smarc *pp = p->p_pgrpnxt; 21257055Smarc break; 21335810Smarc } 21457055Smarc } 21557055Smarc #ifdef DIAGNOSTIC 21657055Smarc if (pp == NULL) 21757055Smarc panic("enterpgrp: can't find p on old pgrp"); 21857055Smarc #endif 21935810Smarc /* 22045673Skarels * delete old if empty 22145673Skarels */ 22245673Skarels if (p->p_pgrp->pg_mem == 0) 22345673Skarels pgdelete(p->p_pgrp); 22445673Skarels /* 22535810Smarc * link into new one 22635810Smarc */ 22745673Skarels p->p_pgrp = pgrp; 22835810Smarc p->p_pgrpnxt = pgrp->pg_mem; 22935810Smarc pgrp->pg_mem = p; 23057055Smarc return (0); 23135810Smarc } 23235810Smarc 23335810Smarc /* 23435810Smarc * remove process from process group 23535810Smarc */ 23647542Skarels leavepgrp(p) 23735810Smarc register struct proc *p; 23835810Smarc { 23935810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 24035810Smarc 24157055Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) { 24235810Smarc if (*pp == p) { 24335810Smarc *pp = p->p_pgrpnxt; 24457055Smarc break; 24535810Smarc } 24657055Smarc } 24757055Smarc #ifdef DIAGNOSTIC 24857055Smarc if (pp == NULL) 24957055Smarc panic("leavepgrp: can't find p in pgrp"); 25057055Smarc #endif 25135810Smarc if (!p->p_pgrp->pg_mem) 25235810Smarc pgdelete(p->p_pgrp); 25335810Smarc p->p_pgrp = 0; 25457055Smarc return (0); 25535810Smarc } 25635810Smarc 25735810Smarc /* 25835810Smarc * delete a process group 25935810Smarc */ 26035810Smarc pgdelete(pgrp) 26135810Smarc register struct pgrp *pgrp; 26235810Smarc { 26335810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 26435810Smarc 26539562Smarc if (pgrp->pg_session->s_ttyp != NULL && 26639562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 26739562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 26857055Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) { 26935810Smarc if (*pgp == pgrp) { 27035810Smarc *pgp = pgrp->pg_hforw; 27157055Smarc break; 27235810Smarc } 27357055Smarc } 27457055Smarc #ifdef DIAGNOSTIC 27557055Smarc if (pgp == NULL) 27657055Smarc panic("pgdelete: can't find pgrp on hash chain"); 27757055Smarc #endif 27835810Smarc if (--pgrp->pg_session->s_count == 0) 27935810Smarc FREE(pgrp->pg_session, M_SESSION); 28035810Smarc FREE(pgrp, M_PGRP); 28135810Smarc } 28235810Smarc 28352494Storek static void orphanpg(); 28448417Skarels 28535810Smarc /* 28645673Skarels * Adjust pgrp jobc counters when specified process changes process group. 28745673Skarels * We count the number of processes in each process group that "qualify" 28845673Skarels * the group for terminal job control (those with a parent in a different 28945673Skarels * process group of the same session). If that count reaches zero, the 29045673Skarels * process group becomes orphaned. Check both the specified process' 29145673Skarels * process group and that of its children. 29245673Skarels * entering == 0 => p is leaving specified group. 29345673Skarels * entering == 1 => p is entering specified group. 29444387Smarc */ 29545673Skarels fixjobc(p, pgrp, entering) 29644387Smarc register struct proc *p; 29745673Skarels register struct pgrp *pgrp; 29845673Skarels int entering; 29944387Smarc { 30045673Skarels register struct pgrp *hispgrp; 30145673Skarels register struct session *mysession = pgrp->pg_session; 30244387Smarc 30345673Skarels /* 30445673Skarels * Check p's parent to see whether p qualifies its own process 30545673Skarels * group; if so, adjust count for p's process group. 30645673Skarels */ 30745673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 30844387Smarc hispgrp->pg_session == mysession) 30945673Skarels if (entering) 31045673Skarels pgrp->pg_jobc++; 31145673Skarels else if (--pgrp->pg_jobc == 0) 31245673Skarels orphanpg(pgrp); 31344387Smarc 31445673Skarels /* 31545673Skarels * Check this process' children to see whether they qualify 31645673Skarels * their process groups; if so, adjust counts for children's 31745673Skarels * process groups. 31845673Skarels */ 31945673Skarels for (p = p->p_cptr; p; p = p->p_osptr) 32045673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 32144387Smarc hispgrp->pg_session == mysession && 32244387Smarc p->p_stat != SZOMB) 32345673Skarels if (entering) 32444387Smarc hispgrp->pg_jobc++; 32545673Skarels else if (--hispgrp->pg_jobc == 0) 32645673Skarels orphanpg(hispgrp); 32745673Skarels } 32844387Smarc 32945673Skarels /* 33045673Skarels * A process group has become orphaned; 33145673Skarels * if there are any stopped processes in the group, 33245673Skarels * hang-up all process in that group. 33345673Skarels */ 33452494Storek static void 33545673Skarels orphanpg(pg) 33645673Skarels struct pgrp *pg; 33745673Skarels { 33845673Skarels register struct proc *p; 33945673Skarels 34045673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 34145673Skarels if (p->p_stat == SSTOP) { 34245673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 34345673Skarels psignal(p, SIGHUP); 34445673Skarels psignal(p, SIGCONT); 34544387Smarc } 34645673Skarels return; 34745673Skarels } 34845673Skarels } 34944387Smarc } 35045673Skarels 35137728Smckusick #ifdef debug 35235810Smarc /* DEBUG */ 35335810Smarc pgrpdump() 35435810Smarc { 35535810Smarc register struct pgrp *pgrp; 35635810Smarc register struct proc *p; 35735810Smarc register i; 35835810Smarc 35935810Smarc for (i=0; i<PIDHSZ; i++) { 36035810Smarc if (pgrphash[i]) { 36135810Smarc printf("\tindx %d\n", i); 36235810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 36335810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 36435810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 36535810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 36635810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 36735810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 36835810Smarc p->p_pid, p, p->p_pgrp); 36935810Smarc } 37035810Smarc } 37135810Smarc 37235810Smarc } 37335810Smarc } 37435810Smarc } 37537728Smckusick #endif /* debug */ 376