Commit | Line | Data |
---|---|---|
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 | */ | |
17 | struct inode *acctp; | |
18 | struct inode *savacctp; | |
19 | ||
20 | /* | |
21 | * Perform process accounting functions. | |
22 | */ | |
23 | sysacct() | |
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 | ||
58 | int acctsuspend = 2; /* stop accounting when < 2% free space left */ | |
59 | int acctresume = 4; /* resume when free space risen to > 4% */ | |
60 | ||
61 | struct acct acctbuf; | |
62 | /* | |
63 | * On exit, write a record on the accounting file. | |
64 | */ | |
65 | acct() | |
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 | */ | |
123 | compress(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 | } |