123373Smckusick /* 229093Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323373Smckusick * All rights reserved. The Berkeley software License Agreement 423373Smckusick * specifies the terms and conditions for redistribution. 523373Smckusick * 6*44405Skarels * @(#)kern_resource.c 7.9 (Berkeley) 06/28/90 723373Smckusick */ 87Sbill 917092Sbloom #include "param.h" 10*44405Skarels #include "user.h" 1117092Sbloom #include "proc.h" 127Sbill 138176Sroot /* 148176Sroot * Resource controls and accounting. 158176Sroot */ 168176Sroot 1743365Smckusick getpriority(curp, uap, retval) 1843365Smckusick struct proc *curp; 1943365Smckusick register struct args { 208031Sroot int which; 218031Sroot int who; 2243365Smckusick } *uap; 2343365Smckusick int *retval; 2443365Smckusick { 258031Sroot register struct proc *p; 2635810Smarc register int low = PRIO_MAX + 1; 278031Sroot 288031Sroot switch (uap->which) { 298031Sroot 308031Sroot case PRIO_PROCESS: 318031Sroot if (uap->who == 0) 3243365Smckusick p = curp; 338031Sroot else 348031Sroot p = pfind(uap->who); 358031Sroot if (p == 0) 3628149Skarels break; 3717400Skarels low = p->p_nice; 388031Sroot break; 398031Sroot 4035810Smarc case PRIO_PGRP: { 4135810Smarc register struct pgrp *pg; 4235810Smarc 438031Sroot if (uap->who == 0) 4443365Smckusick pg = curp->p_pgrp; 4535810Smarc else if ((pg = pgfind(uap->who)) == NULL) 4635810Smarc break; 4735810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 4835810Smarc if (p->p_nice < low) 4917400Skarels low = p->p_nice; 508176Sroot } 518031Sroot break; 5235810Smarc } 538031Sroot 548176Sroot case PRIO_USER: 558176Sroot if (uap->who == 0) 5643365Smckusick uap->who = p->p_uid; 5716530Skarels for (p = allproc; p != NULL; p = p->p_nxt) { 588176Sroot if (p->p_uid == uap->who && 5917400Skarels p->p_nice < low) 6017400Skarels low = p->p_nice; 618176Sroot } 628176Sroot break; 638176Sroot 648031Sroot default: 65*44405Skarels return (EINVAL); 668031Sroot } 6743365Smckusick if (low == PRIO_MAX + 1) 68*44405Skarels return (ESRCH); 6943365Smckusick *retval = low; 70*44405Skarels return (0); 718031Sroot } 728031Sroot 7343365Smckusick /* ARGSUSED */ 7443365Smckusick setpriority(curp, uap, retval) 7543365Smckusick struct proc *curp; 7643365Smckusick register struct args { 778031Sroot int which; 788031Sroot int who; 798031Sroot int prio; 8043365Smckusick } *uap; 8143365Smckusick int *retval; 8243365Smckusick { 838031Sroot register struct proc *p; 8443365Smckusick int found = 0, error = 0; 858031Sroot 868031Sroot switch (uap->which) { 878031Sroot 888031Sroot case PRIO_PROCESS: 898176Sroot if (uap->who == 0) 9043365Smckusick p = curp; 918176Sroot else 928176Sroot p = pfind(uap->who); 938031Sroot if (p == 0) 9428149Skarels break; 9543365Smckusick error = donice(curp, p, uap->prio); 9617400Skarels found++; 978031Sroot break; 988031Sroot 9935810Smarc case PRIO_PGRP: { 10035810Smarc register struct pgrp *pg; 10135810Smarc 1028176Sroot if (uap->who == 0) 10343365Smckusick pg = curp->p_pgrp; 10435810Smarc else if ((pg = pgfind(uap->who)) == NULL) 10535810Smarc break; 10635810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 10743365Smckusick error = donice(curp, p, uap->prio); 10835810Smarc found++; 10935810Smarc } 1108031Sroot break; 11135810Smarc } 1128031Sroot 1138176Sroot case PRIO_USER: 1148176Sroot if (uap->who == 0) 11543365Smckusick uap->who = p->p_uid; 11616530Skarels for (p = allproc; p != NULL; p = p->p_nxt) 11717400Skarels if (p->p_uid == uap->who) { 11843365Smckusick error = donice(curp, p, uap->prio); 11917400Skarels found++; 12017400Skarels } 1218176Sroot break; 1228176Sroot 1238031Sroot default: 124*44405Skarels return (EINVAL); 1258031Sroot } 12617400Skarels if (found == 0) 127*44405Skarels return (ESRCH); 128*44405Skarels return (0); 1298031Sroot } 1308031Sroot 13143365Smckusick donice(curp, chgp, n) 13243365Smckusick register struct proc *curp, *chgp; 1338031Sroot register int n; 1348031Sroot { 1358031Sroot 13643365Smckusick if (curp->p_uid && curp->p_ruid && 13743365Smckusick curp->p_uid != chgp->p_uid && curp->p_ruid != chgp->p_uid) 13843365Smckusick return (EPERM); 13917400Skarels if (n > PRIO_MAX) 14017400Skarels n = PRIO_MAX; 14117400Skarels if (n < PRIO_MIN) 14217400Skarels n = PRIO_MIN; 14343365Smckusick if (n < chgp->p_nice && suser(u.u_cred, &u.u_acflag)) 14443365Smckusick return (EACCES); 14543365Smckusick chgp->p_nice = n; 14643365Smckusick (void) setpri(chgp); 14743365Smckusick return (0); 1488031Sroot } 1498031Sroot 15043365Smckusick /* ARGSUSED */ 15143365Smckusick setrlimit(p, uap, retval) 15243365Smckusick struct proc *p; 15343365Smckusick register struct args { 1548031Sroot u_int which; 1558031Sroot struct rlimit *lim; 15643365Smckusick } *uap; 15743365Smckusick int *retval; 15843365Smckusick { 1598031Sroot struct rlimit alim; 1608031Sroot register struct rlimit *alimp; 16125257Skarels extern unsigned maxdmap; 16243365Smckusick int error; 1638031Sroot 16443365Smckusick if (uap->which >= RLIM_NLIMITS) 165*44405Skarels return (EINVAL); 1668031Sroot alimp = &u.u_rlimit[uap->which]; 16743365Smckusick if (error = 16843365Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 169*44405Skarels return (error); 1708031Sroot if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 17143365Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 172*44405Skarels return (error); 1738031Sroot switch (uap->which) { 1748031Sroot 1758031Sroot case RLIMIT_DATA: 17618279Smckusick if (alim.rlim_cur > maxdmap) 17718279Smckusick alim.rlim_cur = maxdmap; 17818279Smckusick if (alim.rlim_max > maxdmap) 17918279Smckusick alim.rlim_max = maxdmap; 1808031Sroot break; 1818031Sroot 1828031Sroot case RLIMIT_STACK: 18318279Smckusick if (alim.rlim_cur > maxdmap) 18418279Smckusick alim.rlim_cur = maxdmap; 18518279Smckusick if (alim.rlim_max > maxdmap) 18618279Smckusick alim.rlim_max = maxdmap; 1878031Sroot break; 1888031Sroot } 1898031Sroot *alimp = alim; 1908031Sroot if (uap->which == RLIMIT_RSS) 19143365Smckusick p->p_maxrss = alim.rlim_cur/NBPG; 192*44405Skarels return (0); 1938031Sroot } 1948031Sroot 19543365Smckusick /* ARGSUSED */ 19643365Smckusick getrlimit(p, uap, retval) 19743365Smckusick struct proc *p; 19843365Smckusick register struct args { 1998031Sroot u_int which; 2008031Sroot struct rlimit *rlp; 20143365Smckusick } *uap; 20243365Smckusick int *retval; 20343365Smckusick { 2048031Sroot 20543365Smckusick if (uap->which >= RLIM_NLIMITS) 206*44405Skarels return (EINVAL); 207*44405Skarels return (copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp, 20843365Smckusick sizeof (struct rlimit))); 2098031Sroot } 2108031Sroot 21143365Smckusick /* ARGSUSED */ 21243365Smckusick getrusage(p, uap, retval) 21343365Smckusick register struct proc *p; 21443365Smckusick register struct args { 2158031Sroot int who; 2168031Sroot struct rusage *rusage; 21743365Smckusick } *uap; 21843365Smckusick int *retval; 21943365Smckusick { 2208031Sroot register struct rusage *rup; 2218031Sroot 2228031Sroot switch (uap->who) { 2238031Sroot 22440705Skarels case RUSAGE_SELF: { 22540705Skarels int s; 22640705Skarels 2278031Sroot rup = &u.u_ru; 22840705Skarels s = splclock(); 22940705Skarels rup->ru_stime = p->p_stime; 23040705Skarels rup->ru_utime = p->p_utime; 23140705Skarels splx(s); 2328031Sroot break; 23340705Skarels } 2348031Sroot 2358031Sroot case RUSAGE_CHILDREN: 2368031Sroot rup = &u.u_cru; 2378031Sroot break; 2388031Sroot 2398031Sroot default: 240*44405Skarels return (EINVAL); 2418031Sroot } 242*44405Skarels return (copyout((caddr_t)rup, (caddr_t)uap->rusage, 24343365Smckusick sizeof (struct rusage))); 2448031Sroot } 2458031Sroot 2468031Sroot ruadd(ru, ru2) 2478031Sroot register struct rusage *ru, *ru2; 2488031Sroot { 2498666Sroot register long *ip, *ip2; 2508031Sroot register int i; 2518031Sroot 2528031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 2538031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 2548031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 2558031Sroot ru->ru_maxrss = ru2->ru_maxrss; 2568031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 2578031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 2588031Sroot *ip++ += *ip2++; 2598031Sroot } 260