/* @(#)acct.c 1.2 */ #include "sys/param.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/acct.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/inode.h" #include "sys/file.h" /* * Perform process accounting functions. */ sysacct() { register struct inode *ip; register struct a { char *fname; } *uap; static aclock; uap = (struct a *)u.u_ap; if (aclock || !suser()) return; aclock++; switch (uap->fname) { case NULL: if (acctp) { plock(acctp); iput(acctp); acctp = NULL; } break; default: if (acctp) { u.u_error = EBUSY; break; } ip = namei(uchar, 0); if (ip == NULL) break; if ((ip->i_mode & IFMT) != IFREG) u.u_error = EACCES; else (void) access(ip, IWRITE); if (u.u_error) { iput(ip); break; } acctp = ip; prele(ip); } aclock--; } /* * On exit, write a record on the accounting file. */ acct(st) { register struct inode *ip; register struct user *up; register struct acct *ap; off_t siz; if ((ip=acctp) == NULL) return; up = &u; plock(ip); ap = &acctbuf; bcopy((caddr_t)up->u_comm, (caddr_t)ap->ac_comm, sizeof(ap->ac_comm)); ap->ac_btime = up->u_start; ap->ac_utime = compress(up->u_utime); ap->ac_stime = compress(up->u_stime); ap->ac_etime = compress(lbolt - up->u_ticks); ap->ac_mem = compress(up->u_mem); ap->ac_io = compress(up->u_ioch); ap->ac_rw = compress(up->u_ior+up->u_iow); ap->ac_uid = up->u_ruid; ap->ac_gid = up->u_rgid; ap->ac_tty = up->u_ttyp ? up->u_ttyd : NODEV; ap->ac_stat = st; ap->ac_flag = up->u_acflag; siz = ip->i_size; up->u_offset = siz; up->u_base = (caddr_t)ap; up->u_count = sizeof(acctbuf); up->u_segflg = 1; up->u_error = 0; up->u_limit = (daddr_t)5000; up->u_fmode = FWRITE; writei(ip); if (up->u_error) ip->i_size = siz; prele(ip); } /* * Produce a pseudo-floating point representation * with 3 bits base-8 exponent, 13 bits fraction. */ compress(t) register time_t 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); }