/* kern_resource.c 4.12 82/09/04 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/acct.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/inode.h" #include "../h/proc.h" #include "../h/seg.h" #include "../h/fs.h" #include "../h/uio.h" #include "../h/vm.h" getpriority() { register struct a { int which; int who; } *uap = (struct a *)u.u_ap; register struct proc *p; u.u_r.r_val1 = NZERO+20; u.u_error = ESRCH; switch (uap->which) { case PRIO_PROCESS: if (uap->who == 0) p = u.u_procp; else p = pfind(uap->who); if (p == 0) return; u.u_r.r_val1 = u.u_procp->p_nice; break; case PRIO_PGRP: if (uap->who == 0) uap->who = u.u_procp->p_pgrp; for (p = proc; p < procNPROC; p++) if (p->p_pgrp == uap->who && p->p_nice < u.u_r.r_val1) { u.u_r.r_val1 = p->p_nice; u.u_error = 0; } break; default: u.u_error = EINVAL; break; } u.u_r.r_val1 -= NZERO; } setpriority() { register struct a { int which; int who; int prio; } *uap = (struct a *)u.u_ap; register struct proc *p; u.u_error = ESRCH; switch (uap->which) { case PRIO_PROCESS: p = pfind(uap->who); if (p == 0) return; donice(p, uap->prio); break; case PRIO_PGRP: for (p = proc; p < procNPROC; p++) if (p->p_pgrp == uap->who) donice(p, uap->prio); break; default: u.u_error = EINVAL; break; } } donice(p, n) register struct proc *p; register int n; { if (u.u_uid && u.u_ruid && u.u_uid != p->p_uid && u.u_ruid != p->p_uid) { u.u_error = EPERM; return; } n += p->p_nice; if (n >= 2*NZERO) n = 2*NZERO - 1; if (n < 0) n = 0; if (n < p->p_nice && !suser()) return; p->p_nice = n; (void) setpri(p); if (u.u_error == ESRCH) u.u_error = 0; } setlimit() { register struct a { u_int which; struct rlimit *lim; } *uap = (struct a *)u.u_ap; struct rlimit alim; register struct rlimit *alimp; if (uap->which >= RLIM_NLIMITS) { u.u_error = EINVAL; return; } alimp = &u.u_rlimit[uap->which]; if (copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) { u.u_error = EFAULT; return; } if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) if (!suser()) return; switch (uap->which) { case RLIMIT_DATA: if (alim.rlim_cur > ctob(MAXDSIZ)) alim.rlim_cur = ctob(MAXDSIZ); break; case RLIMIT_STACK: if (alim.rlim_cur > ctob(MAXSSIZ)) alim.rlim_cur = ctob(MAXSSIZ); break; } *alimp = alim; if (uap->which == RLIMIT_RSS) u.u_procp->p_maxrss = alim.rlim_cur/NBPG; } getlimit() { register struct a { u_int which; struct rlimit *rlp; } *uap = (struct a *)u.u_ap; if (uap->which >= RLIM_NLIMITS) { u.u_error = EINVAL; return; } if (copyout((caddr_t)&u.u_rlimit[uap->which], uap->rlp, sizeof (struct rlimit))) { u.u_error = EFAULT; return; } } getrusage() { register struct a { int who; struct rusage *rusage; } *uap = (struct a *)u.u_ap; register struct rusage *rup; switch (uap->who) { case RUSAGE_SELF: rup = &u.u_ru; break; case RUSAGE_CHILDREN: rup = &u.u_cru; break; default: u.u_error = EINVAL; return; } if (copyout((caddr_t)rup, uap->rusage, sizeof (struct rusage))) { u.u_error = EFAULT; return; } } ruadd(ru, ru2) register struct rusage *ru, *ru2; { register int *ip, *ip2; register int i; timevaladd(&ru->ru_utime, &ru2->ru_utime); timevaladd(&ru->ru_stime, &ru2->ru_stime); if (ru->ru_maxrss < ru2->ru_maxrss) ru->ru_maxrss = ru2->ru_maxrss; ip = &ru->ru_first; ip2 = &ru2->ru_first; for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) *ip++ += *ip2++; } struct inode *acctp; struct inode *savacctp; long acctlow = 2; /* stop accounting when < 2% data space left */ long accthigh = 4; /* resume when space risen to > 4% */ /* * Perform process accounting functions. */ sysacct() { register struct inode *ip; register struct a { char *fname; } *uap; uap = (struct a *)u.u_ap; if (suser()) { if (savacctp) { acctp = savacctp; savacctp = NULL; } if (uap->fname==NULL) { if (ip = acctp) { irele(ip); acctp = NULL; } return; } ip = namei(uchar, 0, 1); if(ip == NULL) return; if((ip->i_mode & IFMT) != IFREG) { u.u_error = EACCES; iput(ip); return; } if (acctp && (acctp->i_number != ip->i_number || acctp->i_dev != ip->i_dev)) irele(acctp); acctp = ip; iunlock(ip); } } struct acct acctbuf; /* * On exit, write a record on the accounting file. */ acct() { register i; register struct inode *ip; off_t siz; register struct acct *ap = &acctbuf; if (savacctp && savacctp->i_fs->fs_cstotal.cs_nbfree > accthigh * savacctp->i_fs->fs_dsize / 100) { acctp = savacctp; savacctp = NULL; printf("Accounting resumed\n"); } if ((ip=acctp)==NULL) return; if (acctp->i_fs->fs_cstotal.cs_nbfree < acctlow * acctp->i_fs->fs_dsize / 100) { savacctp = acctp; acctp = NULL; printf("Accounting suspended\n"); return; } ilock(ip); for (i=0; iac_comm); i++) ap->ac_comm[i] = u.u_comm[i]; ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec); ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec); ap->ac_etime = compress((long)(time - u.u_start)); ap->ac_btime = u.u_start; ap->ac_uid = u.u_ruid; ap->ac_gid = u.u_rgid; ap->ac_mem = 0; if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec) ap->ac_mem = (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock)); if (u.u_ttyp) ap->ac_tty = u.u_ttyd; else ap->ac_tty = NODEV; ap->ac_flag = u.u_acflag; siz = ip->i_size; u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz, 1, (int *)0); if (u.u_error) ip->i_size = siz; iunlock(ip); } /* * Produce a pseudo-floating point representation * with 3 bits base-8 exponent, 13 bits fraction. */ compress(t) register long t; { register exp = 0, round = 0; while (t >= 8192) { exp++; round = t&04; t >>= 3; } if (round) { t++; if (t >= 8192) { t >>= 3; exp++; } } return((exp<<13) + t); } #ifndef NOCOMPAT onice() { register struct a { int niceness; } *uap; uap = (struct a *)u.u_ap; donice(u.u_procp, uap->niceness); } #endif