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