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*64589Sbostic * @(#)kern_proc.c 8.3 (Berkeley) 09/23/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) 10864534Sbostic register pid_t pid; 1097816Sroot { 11064534Sbostic register struct proc *p; 1117816Sroot 11264534Sbostic for (p = pidhash[PIDHASH(pid)]; p != NULL; p = p->p_hash) 1137816Sroot if (p->p_pid == pid) 1147816Sroot return (p); 11564534Sbostic return (NULL); 1167816Sroot } 11716529Skarels 11816529Skarels /* 11935810Smarc * Locate a process group by number 12035810Smarc */ 12135810Smarc struct pgrp * 12235810Smarc pgfind(pgid) 12335810Smarc register pid_t pgid; 12435810Smarc { 12564534Sbostic register struct pgrp *pgrp; 12635810Smarc 12764534Sbostic for (pgrp = pgrphash[PIDHASH(pgid)]; 12864534Sbostic pgrp != NULL; pgrp = pgrp->pg_hforw) 12935810Smarc if (pgrp->pg_id == pgid) 13040709Skarels return (pgrp); 13164534Sbostic return (NULL); 13235810Smarc } 13335810Smarc 13435810Smarc /* 13535810Smarc * Move p to a new or existing process group (and session) 13635810Smarc */ 13747542Skarels enterpgrp(p, pgid, mksess) 13835810Smarc register struct proc *p; 13935810Smarc pid_t pgid; 14052494Storek int mksess; 14135810Smarc { 14235810Smarc register struct pgrp *pgrp = pgfind(pgid); 14345673Skarels register struct proc **pp; 14435810Smarc register struct proc *cp; 14545673Skarels int n; 14635810Smarc 14739562Smarc #ifdef DIAGNOSTIC 14864534Sbostic if (pgrp != NULL && mksess) /* firewalls */ 14947542Skarels panic("enterpgrp: setsid into non-empty pgrp"); 15035810Smarc if (SESS_LEADER(p)) 15147542Skarels panic("enterpgrp: session leader attempted setpgrp"); 15239562Smarc #endif 15337589Smarc if (pgrp == NULL) { 15457055Smarc pid_t savepid = p->p_pid; 15557055Smarc struct proc *np; 15635810Smarc /* 15735810Smarc * new process group 15835810Smarc */ 15939562Smarc #ifdef DIAGNOSTIC 16035810Smarc if (p->p_pid != pgid) 16147542Skarels panic("enterpgrp: new pgrp and pid != pgid"); 16239562Smarc #endif 16335810Smarc MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 16435810Smarc M_WAITOK); 16557055Smarc if ((np = pfind(savepid)) == NULL || np != p) 16657055Smarc return (ESRCH); 16735810Smarc if (mksess) { 16835810Smarc register struct session *sess; 16950252Skarels 17035810Smarc /* 17135810Smarc * new session 17235810Smarc */ 17335810Smarc MALLOC(sess, struct session *, sizeof(struct session), 17435810Smarc M_SESSION, M_WAITOK); 17535810Smarc sess->s_leader = p; 17635810Smarc sess->s_count = 1; 17739562Smarc sess->s_ttyvp = NULL; 17839562Smarc sess->s_ttyp = NULL; 17950252Skarels bcopy(p->p_session->s_login, sess->s_login, 18050252Skarels sizeof(sess->s_login)); 181*64589Sbostic p->p_flag &= ~P_CONTROLT; 18235810Smarc pgrp->pg_session = sess; 18339562Smarc #ifdef DIAGNOSTIC 18447542Skarels if (p != curproc) 18547542Skarels panic("enterpgrp: mksession and p != curproc"); 18639562Smarc #endif 18735810Smarc } else { 18835810Smarc pgrp->pg_session = p->p_session; 18935810Smarc pgrp->pg_session->s_count++; 19035810Smarc } 19135810Smarc pgrp->pg_id = pgid; 19245673Skarels pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; 19335810Smarc pgrphash[n] = pgrp; 19435810Smarc pgrp->pg_jobc = 0; 19539562Smarc pgrp->pg_mem = NULL; 19644387Smarc } else if (pgrp == p->p_pgrp) 19757055Smarc return (0); 19845673Skarels 19935810Smarc /* 20045673Skarels * Adjust eligibility of affected pgrps to participate in job control. 20145673Skarels * Increment eligibility counts before decrementing, otherwise we 20245673Skarels * could reach 0 spuriously during the first call. 20335810Smarc */ 20445673Skarels fixjobc(p, pgrp, 1); 20545673Skarels fixjobc(p, p->p_pgrp, 0); 20645673Skarels 20735810Smarc /* 20835810Smarc * unlink p from old process group 20935810Smarc */ 21057055Smarc for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) { 21135810Smarc if (*pp == p) { 21235810Smarc *pp = p->p_pgrpnxt; 21357055Smarc break; 21435810Smarc } 21557055Smarc } 21657055Smarc #ifdef DIAGNOSTIC 21757055Smarc if (pp == NULL) 21857055Smarc panic("enterpgrp: can't find p on old pgrp"); 21957055Smarc #endif 22035810Smarc /* 22145673Skarels * delete old if empty 22245673Skarels */ 22345673Skarels if (p->p_pgrp->pg_mem == 0) 22445673Skarels pgdelete(p->p_pgrp); 22545673Skarels /* 22635810Smarc * link into new one 22735810Smarc */ 22845673Skarels p->p_pgrp = pgrp; 22935810Smarc p->p_pgrpnxt = pgrp->pg_mem; 23035810Smarc pgrp->pg_mem = p; 23157055Smarc return (0); 23235810Smarc } 23335810Smarc 23435810Smarc /* 23535810Smarc * remove process from process group 23635810Smarc */ 23747542Skarels leavepgrp(p) 23835810Smarc register struct proc *p; 23935810Smarc { 24035810Smarc register struct proc **pp = &p->p_pgrp->pg_mem; 24135810Smarc 24257055Smarc for (; *pp; pp = &(*pp)->p_pgrpnxt) { 24335810Smarc if (*pp == p) { 24435810Smarc *pp = p->p_pgrpnxt; 24557055Smarc break; 24635810Smarc } 24757055Smarc } 24857055Smarc #ifdef DIAGNOSTIC 24957055Smarc if (pp == NULL) 25057055Smarc panic("leavepgrp: can't find p in pgrp"); 25157055Smarc #endif 25235810Smarc if (!p->p_pgrp->pg_mem) 25335810Smarc pgdelete(p->p_pgrp); 25435810Smarc p->p_pgrp = 0; 25557055Smarc return (0); 25635810Smarc } 25735810Smarc 25835810Smarc /* 25935810Smarc * delete a process group 26035810Smarc */ 26135810Smarc pgdelete(pgrp) 26235810Smarc register struct pgrp *pgrp; 26335810Smarc { 26435810Smarc register struct pgrp **pgp = &pgrphash[PIDHASH(pgrp->pg_id)]; 26535810Smarc 26639562Smarc if (pgrp->pg_session->s_ttyp != NULL && 26739562Smarc pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 26839562Smarc pgrp->pg_session->s_ttyp->t_pgrp = NULL; 26957055Smarc for (; *pgp; pgp = &(*pgp)->pg_hforw) { 27035810Smarc if (*pgp == pgrp) { 27135810Smarc *pgp = pgrp->pg_hforw; 27257055Smarc break; 27335810Smarc } 27457055Smarc } 27557055Smarc #ifdef DIAGNOSTIC 27657055Smarc if (pgp == NULL) 27757055Smarc panic("pgdelete: can't find pgrp on hash chain"); 27857055Smarc #endif 27935810Smarc if (--pgrp->pg_session->s_count == 0) 28035810Smarc FREE(pgrp->pg_session, M_SESSION); 28135810Smarc FREE(pgrp, M_PGRP); 28235810Smarc } 28335810Smarc 28452494Storek static void orphanpg(); 28548417Skarels 28635810Smarc /* 28745673Skarels * Adjust pgrp jobc counters when specified process changes process group. 28845673Skarels * We count the number of processes in each process group that "qualify" 28945673Skarels * the group for terminal job control (those with a parent in a different 29045673Skarels * process group of the same session). If that count reaches zero, the 29145673Skarels * process group becomes orphaned. Check both the specified process' 29245673Skarels * process group and that of its children. 29345673Skarels * entering == 0 => p is leaving specified group. 29445673Skarels * entering == 1 => p is entering specified group. 29544387Smarc */ 29645673Skarels fixjobc(p, pgrp, entering) 29744387Smarc register struct proc *p; 29845673Skarels register struct pgrp *pgrp; 29945673Skarels int entering; 30044387Smarc { 30145673Skarels register struct pgrp *hispgrp; 30245673Skarels register struct session *mysession = pgrp->pg_session; 30344387Smarc 30445673Skarels /* 30545673Skarels * Check p's parent to see whether p qualifies its own process 30645673Skarels * group; if so, adjust count for p's process group. 30745673Skarels */ 30845673Skarels if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 30944387Smarc hispgrp->pg_session == mysession) 31045673Skarels if (entering) 31145673Skarels pgrp->pg_jobc++; 31245673Skarels else if (--pgrp->pg_jobc == 0) 31345673Skarels orphanpg(pgrp); 31444387Smarc 31545673Skarels /* 31645673Skarels * Check this process' children to see whether they qualify 31745673Skarels * their process groups; if so, adjust counts for children's 31845673Skarels * process groups. 31945673Skarels */ 32045673Skarels for (p = p->p_cptr; p; p = p->p_osptr) 32145673Skarels if ((hispgrp = p->p_pgrp) != pgrp && 32244387Smarc hispgrp->pg_session == mysession && 32344387Smarc p->p_stat != SZOMB) 32445673Skarels if (entering) 32544387Smarc hispgrp->pg_jobc++; 32645673Skarels else if (--hispgrp->pg_jobc == 0) 32745673Skarels orphanpg(hispgrp); 32845673Skarels } 32944387Smarc 33045673Skarels /* 33145673Skarels * A process group has become orphaned; 33245673Skarels * if there are any stopped processes in the group, 33345673Skarels * hang-up all process in that group. 33445673Skarels */ 33552494Storek static void 33645673Skarels orphanpg(pg) 33745673Skarels struct pgrp *pg; 33845673Skarels { 33945673Skarels register struct proc *p; 34045673Skarels 34145673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 34245673Skarels if (p->p_stat == SSTOP) { 34345673Skarels for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { 34445673Skarels psignal(p, SIGHUP); 34545673Skarels psignal(p, SIGCONT); 34644387Smarc } 34745673Skarels return; 34845673Skarels } 34945673Skarels } 35044387Smarc } 35145673Skarels 35237728Smckusick #ifdef debug 35335810Smarc /* DEBUG */ 35435810Smarc pgrpdump() 35535810Smarc { 35635810Smarc register struct pgrp *pgrp; 35735810Smarc register struct proc *p; 35835810Smarc register i; 35935810Smarc 36035810Smarc for (i=0; i<PIDHSZ; i++) { 36135810Smarc if (pgrphash[i]) { 36235810Smarc printf("\tindx %d\n", i); 36335810Smarc for (pgrp=pgrphash[i]; pgrp; pgrp=pgrp->pg_hforw) { 36435810Smarc printf("\tpgrp %x, pgid %d, sess %x, sesscnt %d, mem %x\n", 36535810Smarc pgrp, pgrp->pg_id, pgrp->pg_session, 36635810Smarc pgrp->pg_session->s_count, pgrp->pg_mem); 36735810Smarc for (p=pgrp->pg_mem; p; p=p->p_pgrpnxt) { 36835810Smarc printf("\t\tpid %d addr %x pgrp %x\n", 36935810Smarc p->p_pid, p, p->p_pgrp); 37035810Smarc } 37135810Smarc } 37235810Smarc 37335810Smarc } 37435810Smarc } 37535810Smarc } 37637728Smckusick #endif /* debug */ 377