do it "right"?
[unix-history] / usr / src / sys / kern / kern_acct.c
CommitLineData
06138e31
SL
1/* kern_acct.c 4.1 83/05/27 */
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/inode.h"
8#include "../h/fs.h"
9#include "../h/kernel.h"
10#include "../h/acct.h"
11#include "../h/nami.h"
12#include "../h/uio.h"
13
14/*
15 * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
16 */
17struct inode *acctp;
18struct inode *savacctp;
19
20/*
21 * Perform process accounting functions.
22 */
23sysacct()
24{
25 register struct inode *ip;
26 register struct a {
27 char *fname;
28 } *uap = (struct a *)u.u_ap;
29
30 if (suser()) {
31 if (savacctp) {
32 acctp = savacctp;
33 savacctp = NULL;
34 }
35 if (uap->fname==NULL) {
36 if (ip = acctp) {
37 irele(ip);
38 acctp = NULL;
39 }
40 return;
41 }
42 ip = namei(uchar, LOOKUP, 1);
43 if(ip == NULL)
44 return;
45 if((ip->i_mode & IFMT) != IFREG) {
46 u.u_error = EACCES;
47 iput(ip);
48 return;
49 }
50 if (acctp && (acctp->i_number != ip->i_number ||
51 acctp->i_dev != ip->i_dev))
52 irele(acctp);
53 acctp = ip;
54 iunlock(ip);
55 }
56}
57
58int acctsuspend = 2; /* stop accounting when < 2% free space left */
59int acctresume = 4; /* resume when free space risen to > 4% */
60
61struct acct acctbuf;
62/*
63 * On exit, write a record on the accounting file.
64 */
65acct()
66{
67 register int i;
68 register struct inode *ip;
69 register struct fs *fs;
70 off_t siz;
71 register struct acct *ap = &acctbuf;
72
73 if (savacctp) {
74 fs = savacctp->i_fs;
75 if (freespace(fs, fs->fs_minfree + acctresume) > 0) {
76 acctp = savacctp;
77 savacctp = NULL;
78 printf("Accounting resumed\n");
79 }
80 }
81 if ((ip = acctp) == NULL)
82 return;
83 fs = acctp->i_fs;
84 if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) {
85 savacctp = acctp;
86 acctp = NULL;
87 printf("Accounting suspended\n");
88 return;
89 }
90 ilock(ip);
91 for (i = 0; i < sizeof (ap->ac_comm); i++)
92 ap->ac_comm[i] = u.u_comm[i];
93 ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec);
94 ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec);
95 ap->ac_etime = compress((long)time.tv_sec - u.u_start);
96 ap->ac_btime = u.u_start;
97 ap->ac_uid = u.u_ruid;
98 ap->ac_gid = u.u_rgid;
99 ap->ac_mem = 0;
100 if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec)
101 ap->ac_mem =
102 (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i;
103 ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock));
104 if (u.u_ttyp)
105 ap->ac_tty = u.u_ttyd;
106 else
107 ap->ac_tty = NODEV;
108 ap->ac_flag = u.u_acflag;
109 siz = ip->i_size;
110 u.u_error = 0; /* XXX */
111 u.u_error =
112 rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
113 1, (int *)0);
114 if (u.u_error)
115 itrunc(ip, (u_long)siz);
116 iunlock(ip);
117}
118
119/*
120 * Produce a pseudo-floating point representation
121 * with 3 bits base-8 exponent, 13 bits fraction.
122 */
123compress(t)
124 register long t;
125{
126 register exp = 0, round = 0;
127
128 while (t >= 8192) {
129 exp++;
130 round = t&04;
131 t >>= 3;
132 }
133 if (round) {
134 t++;
135 if (t >= 8192) {
136 t >>= 3;
137 exp++;
138 }
139 }
140 return ((exp<<13) + t);
141}