1 /* kern_resource.c 4.12 82/09/04 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/acct.h" 6 #include "../h/dir.h" 7 #include "../h/user.h" 8 #include "../h/inode.h" 9 #include "../h/proc.h" 10 #include "../h/seg.h" 11 #include "../h/fs.h" 12 #include "../h/uio.h" 13 #include "../h/vm.h" 14 15 getpriority() 16 { 17 register struct a { 18 int which; 19 int who; 20 } *uap = (struct a *)u.u_ap; 21 register struct proc *p; 22 23 u.u_r.r_val1 = NZERO+20; 24 u.u_error = ESRCH; 25 switch (uap->which) { 26 27 case PRIO_PROCESS: 28 if (uap->who == 0) 29 p = u.u_procp; 30 else 31 p = pfind(uap->who); 32 if (p == 0) 33 return; 34 u.u_r.r_val1 = u.u_procp->p_nice; 35 break; 36 37 case PRIO_PGRP: 38 if (uap->who == 0) 39 uap->who = u.u_procp->p_pgrp; 40 for (p = proc; p < procNPROC; p++) 41 if (p->p_pgrp == uap->who && 42 p->p_nice < u.u_r.r_val1) { 43 u.u_r.r_val1 = p->p_nice; 44 u.u_error = 0; 45 } 46 break; 47 48 default: 49 u.u_error = EINVAL; 50 break; 51 } 52 u.u_r.r_val1 -= NZERO; 53 } 54 55 setpriority() 56 { 57 register struct a { 58 int which; 59 int who; 60 int prio; 61 } *uap = (struct a *)u.u_ap; 62 register struct proc *p; 63 64 u.u_error = ESRCH; 65 switch (uap->which) { 66 67 case PRIO_PROCESS: 68 p = pfind(uap->who); 69 if (p == 0) 70 return; 71 donice(p, uap->prio); 72 break; 73 74 case PRIO_PGRP: 75 for (p = proc; p < procNPROC; p++) 76 if (p->p_pgrp == uap->who) 77 donice(p, uap->prio); 78 break; 79 80 default: 81 u.u_error = EINVAL; 82 break; 83 } 84 } 85 86 donice(p, n) 87 register struct proc *p; 88 register int n; 89 { 90 91 if (u.u_uid && u.u_ruid && 92 u.u_uid != p->p_uid && u.u_ruid != p->p_uid) { 93 u.u_error = EPERM; 94 return; 95 } 96 n += p->p_nice; 97 if (n >= 2*NZERO) 98 n = 2*NZERO - 1; 99 if (n < 0) 100 n = 0; 101 if (n < p->p_nice && !suser()) 102 return; 103 p->p_nice = n; 104 (void) setpri(p); 105 if (u.u_error == ESRCH) 106 u.u_error = 0; 107 } 108 109 setlimit() 110 { 111 register struct a { 112 u_int which; 113 struct rlimit *lim; 114 } *uap = (struct a *)u.u_ap; 115 struct rlimit alim; 116 register struct rlimit *alimp; 117 118 if (uap->which >= RLIM_NLIMITS) { 119 u.u_error = EINVAL; 120 return; 121 } 122 alimp = &u.u_rlimit[uap->which]; 123 if (copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) { 124 u.u_error = EFAULT; 125 return; 126 } 127 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 128 if (!suser()) 129 return; 130 switch (uap->which) { 131 132 case RLIMIT_DATA: 133 if (alim.rlim_cur > ctob(MAXDSIZ)) 134 alim.rlim_cur = ctob(MAXDSIZ); 135 break; 136 137 case RLIMIT_STACK: 138 if (alim.rlim_cur > ctob(MAXSSIZ)) 139 alim.rlim_cur = ctob(MAXSSIZ); 140 break; 141 } 142 *alimp = alim; 143 if (uap->which == RLIMIT_RSS) 144 u.u_procp->p_maxrss = alim.rlim_cur/NBPG; 145 } 146 147 getlimit() 148 { 149 register struct a { 150 u_int which; 151 struct rlimit *rlp; 152 } *uap = (struct a *)u.u_ap; 153 154 if (uap->which >= RLIM_NLIMITS) { 155 u.u_error = EINVAL; 156 return; 157 } 158 if (copyout((caddr_t)&u.u_rlimit[uap->which], uap->rlp, 159 sizeof (struct rlimit))) { 160 u.u_error = EFAULT; 161 return; 162 } 163 } 164 165 getrusage() 166 { 167 register struct a { 168 int who; 169 struct rusage *rusage; 170 } *uap = (struct a *)u.u_ap; 171 register struct rusage *rup; 172 173 switch (uap->who) { 174 175 case RUSAGE_SELF: 176 rup = &u.u_ru; 177 break; 178 179 case RUSAGE_CHILDREN: 180 rup = &u.u_cru; 181 break; 182 183 default: 184 u.u_error = EINVAL; 185 return; 186 } 187 if (copyout((caddr_t)rup, uap->rusage, sizeof (struct rusage))) { 188 u.u_error = EFAULT; 189 return; 190 } 191 } 192 193 ruadd(ru, ru2) 194 register struct rusage *ru, *ru2; 195 { 196 register int *ip, *ip2; 197 register int i; 198 199 timevaladd(&ru->ru_utime, &ru2->ru_utime); 200 timevaladd(&ru->ru_stime, &ru2->ru_stime); 201 if (ru->ru_maxrss < ru2->ru_maxrss) 202 ru->ru_maxrss = ru2->ru_maxrss; 203 ip = &ru->ru_first; ip2 = &ru2->ru_first; 204 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 205 *ip++ += *ip2++; 206 } 207 208 struct inode *acctp; 209 struct inode *savacctp; 210 211 long acctlow = 2; /* stop accounting when < 2% data space left */ 212 long accthigh = 4; /* resume when space risen to > 4% */ 213 214 /* 215 * Perform process accounting functions. 216 */ 217 sysacct() 218 { 219 register struct inode *ip; 220 register struct a { 221 char *fname; 222 } *uap; 223 224 uap = (struct a *)u.u_ap; 225 if (suser()) { 226 if (savacctp) { 227 acctp = savacctp; 228 savacctp = NULL; 229 } 230 if (uap->fname==NULL) { 231 if (ip = acctp) { 232 irele(ip); 233 acctp = NULL; 234 } 235 return; 236 } 237 ip = namei(uchar, 0, 1); 238 if(ip == NULL) 239 return; 240 if((ip->i_mode & IFMT) != IFREG) { 241 u.u_error = EACCES; 242 iput(ip); 243 return; 244 } 245 if (acctp && (acctp->i_number != ip->i_number || 246 acctp->i_dev != ip->i_dev)) 247 irele(acctp); 248 acctp = ip; 249 iunlock(ip); 250 } 251 } 252 253 struct acct acctbuf; 254 /* 255 * On exit, write a record on the accounting file. 256 */ 257 acct() 258 { 259 register i; 260 register struct inode *ip; 261 off_t siz; 262 register struct acct *ap = &acctbuf; 263 264 if (savacctp && savacctp->i_fs->fs_cstotal.cs_nbfree > 265 accthigh * savacctp->i_fs->fs_dsize / 100) { 266 acctp = savacctp; 267 savacctp = NULL; 268 printf("Accounting resumed\n"); 269 } 270 if ((ip=acctp)==NULL) 271 return; 272 if (acctp->i_fs->fs_cstotal.cs_nbfree < 273 acctlow * acctp->i_fs->fs_dsize / 100) { 274 savacctp = acctp; 275 acctp = NULL; 276 printf("Accounting suspended\n"); 277 return; 278 } 279 ilock(ip); 280 for (i=0; i<sizeof(ap->ac_comm); i++) 281 ap->ac_comm[i] = u.u_comm[i]; 282 ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec); 283 ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec); 284 ap->ac_etime = compress((long)(time - u.u_start)); 285 ap->ac_btime = u.u_start; 286 ap->ac_uid = u.u_ruid; 287 ap->ac_gid = u.u_rgid; 288 ap->ac_mem = 0; 289 if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec) 290 ap->ac_mem = 291 (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; 292 ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock)); 293 if (u.u_ttyp) 294 ap->ac_tty = u.u_ttyd; 295 else 296 ap->ac_tty = NODEV; 297 ap->ac_flag = u.u_acflag; 298 siz = ip->i_size; 299 u.u_error = 300 rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz, 301 1, (int *)0); 302 if (u.u_error) 303 ip->i_size = siz; 304 iunlock(ip); 305 } 306 307 /* 308 * Produce a pseudo-floating point representation 309 * with 3 bits base-8 exponent, 13 bits fraction. 310 */ 311 compress(t) 312 register long t; 313 { 314 register exp = 0, round = 0; 315 316 while (t >= 8192) { 317 exp++; 318 round = t&04; 319 t >>= 3; 320 } 321 if (round) { 322 t++; 323 if (t >= 8192) { 324 t >>= 3; 325 exp++; 326 } 327 } 328 return((exp<<13) + t); 329 } 330 331 #ifndef NOCOMPAT 332 onice() 333 { 334 register struct a { 335 int niceness; 336 } *uap; 337 338 uap = (struct a *)u.u_ap; 339 donice(u.u_procp, uap->niceness); 340 } 341 #endif 342