1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_resource.c 7.8 (Berkeley) 06/21/90 7 */ 8 9 #include "param.h" 10 #include "syscontext.h" 11 #include "proc.h" 12 13 /* 14 * Resource controls and accounting. 15 */ 16 17 getpriority(curp, uap, retval) 18 struct proc *curp; 19 register struct args { 20 int which; 21 int who; 22 } *uap; 23 int *retval; 24 { 25 register struct proc *p; 26 register int low = PRIO_MAX + 1; 27 28 switch (uap->which) { 29 30 case PRIO_PROCESS: 31 if (uap->who == 0) 32 p = curp; 33 else 34 p = pfind(uap->who); 35 if (p == 0) 36 break; 37 low = p->p_nice; 38 break; 39 40 case PRIO_PGRP: { 41 register struct pgrp *pg; 42 43 if (uap->who == 0) 44 pg = curp->p_pgrp; 45 else if ((pg = pgfind(uap->who)) == NULL) 46 break; 47 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 48 if (p->p_nice < low) 49 low = p->p_nice; 50 } 51 break; 52 } 53 54 case PRIO_USER: 55 if (uap->who == 0) 56 uap->who = p->p_uid; 57 for (p = allproc; p != NULL; p = p->p_nxt) { 58 if (p->p_uid == uap->who && 59 p->p_nice < low) 60 low = p->p_nice; 61 } 62 break; 63 64 default: 65 RETURN (EINVAL); 66 } 67 if (low == PRIO_MAX + 1) 68 RETURN (ESRCH); 69 *retval = low; 70 RETURN (0); 71 } 72 73 /* ARGSUSED */ 74 setpriority(curp, uap, retval) 75 struct proc *curp; 76 register struct args { 77 int which; 78 int who; 79 int prio; 80 } *uap; 81 int *retval; 82 { 83 register struct proc *p; 84 int found = 0, error = 0; 85 86 switch (uap->which) { 87 88 case PRIO_PROCESS: 89 if (uap->who == 0) 90 p = curp; 91 else 92 p = pfind(uap->who); 93 if (p == 0) 94 break; 95 error = donice(curp, p, uap->prio); 96 found++; 97 break; 98 99 case PRIO_PGRP: { 100 register struct pgrp *pg; 101 102 if (uap->who == 0) 103 pg = curp->p_pgrp; 104 else if ((pg = pgfind(uap->who)) == NULL) 105 break; 106 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 107 error = donice(curp, p, uap->prio); 108 found++; 109 } 110 break; 111 } 112 113 case PRIO_USER: 114 if (uap->who == 0) 115 uap->who = p->p_uid; 116 for (p = allproc; p != NULL; p = p->p_nxt) 117 if (p->p_uid == uap->who) { 118 error = donice(curp, p, uap->prio); 119 found++; 120 } 121 break; 122 123 default: 124 RETURN (EINVAL); 125 } 126 if (found == 0) 127 RETURN (ESRCH); 128 RETURN (0); 129 } 130 131 donice(curp, chgp, n) 132 register struct proc *curp, *chgp; 133 register int n; 134 { 135 136 if (curp->p_uid && curp->p_ruid && 137 curp->p_uid != chgp->p_uid && curp->p_ruid != chgp->p_uid) 138 return (EPERM); 139 if (n > PRIO_MAX) 140 n = PRIO_MAX; 141 if (n < PRIO_MIN) 142 n = PRIO_MIN; 143 if (n < chgp->p_nice && suser(u.u_cred, &u.u_acflag)) 144 return (EACCES); 145 chgp->p_nice = n; 146 (void) setpri(chgp); 147 return (0); 148 } 149 150 /* ARGSUSED */ 151 setrlimit(p, uap, retval) 152 struct proc *p; 153 register struct args { 154 u_int which; 155 struct rlimit *lim; 156 } *uap; 157 int *retval; 158 { 159 struct rlimit alim; 160 register struct rlimit *alimp; 161 extern unsigned maxdmap; 162 int error; 163 164 if (uap->which >= RLIM_NLIMITS) 165 RETURN (EINVAL); 166 alimp = &u.u_rlimit[uap->which]; 167 if (error = 168 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 169 RETURN (error); 170 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 171 if (error = suser(u.u_cred, &u.u_acflag)) 172 RETURN (error); 173 switch (uap->which) { 174 175 case RLIMIT_DATA: 176 if (alim.rlim_cur > maxdmap) 177 alim.rlim_cur = maxdmap; 178 if (alim.rlim_max > maxdmap) 179 alim.rlim_max = maxdmap; 180 break; 181 182 case RLIMIT_STACK: 183 if (alim.rlim_cur > maxdmap) 184 alim.rlim_cur = maxdmap; 185 if (alim.rlim_max > maxdmap) 186 alim.rlim_max = maxdmap; 187 break; 188 } 189 *alimp = alim; 190 if (uap->which == RLIMIT_RSS) 191 p->p_maxrss = alim.rlim_cur/NBPG; 192 RETURN (0); 193 } 194 195 /* ARGSUSED */ 196 getrlimit(p, uap, retval) 197 struct proc *p; 198 register struct args { 199 u_int which; 200 struct rlimit *rlp; 201 } *uap; 202 int *retval; 203 { 204 205 if (uap->which >= RLIM_NLIMITS) 206 RETURN (EINVAL); 207 RETURN (copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp, 208 sizeof (struct rlimit))); 209 } 210 211 /* ARGSUSED */ 212 getrusage(p, uap, retval) 213 register struct proc *p; 214 register struct args { 215 int who; 216 struct rusage *rusage; 217 } *uap; 218 int *retval; 219 { 220 register struct rusage *rup; 221 222 switch (uap->who) { 223 224 case RUSAGE_SELF: { 225 int s; 226 227 rup = &u.u_ru; 228 s = splclock(); 229 rup->ru_stime = p->p_stime; 230 rup->ru_utime = p->p_utime; 231 splx(s); 232 break; 233 } 234 235 case RUSAGE_CHILDREN: 236 rup = &u.u_cru; 237 break; 238 239 default: 240 RETURN (EINVAL); 241 } 242 RETURN (copyout((caddr_t)rup, (caddr_t)uap->rusage, 243 sizeof (struct rusage))); 244 } 245 246 ruadd(ru, ru2) 247 register struct rusage *ru, *ru2; 248 { 249 register long *ip, *ip2; 250 register int i; 251 252 timevaladd(&ru->ru_utime, &ru2->ru_utime); 253 timevaladd(&ru->ru_stime, &ru2->ru_stime); 254 if (ru->ru_maxrss < ru2->ru_maxrss) 255 ru->ru_maxrss = ru2->ru_maxrss; 256 ip = &ru->ru_first; ip2 = &ru2->ru_first; 257 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 258 *ip++ += *ip2++; 259 } 260