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