#
/*
 *	This file contains the basic accounting routines for the
 *	ACCT modification
 *	see changes.h
 *
 */
#include	"../param.h"
#define ACCT 0
#include	"../systm.h"
#include	"../user.h"
#include	"../inode.h"
#include	"../buf.h"

/*

 * Structure for accounting
 * same as that for sa
 */

int *acctp 0;
struct acct
{
	char	ac_comm[DIRSIZ];	/* Command for accounting */
	char	ac_shf;			/* Flag - not used */
	char	ac_uid;			/* User id */
	long	ac_time;		/* Time of accounting entry */
	long	ac_etime;		/* elapsed time for process */
	long	ac_utime;		/* user time for process */
	long	ac_stime;		/* system time for process */
};

struct acct *curract;	/* Points at next free entry in table */
struct acct *acbuf;	/* Points at start of buffer for I/O */
struct buf *acctbuf;	/* Points for device type buffer used for I/O */


/*
 * Perform process accounting functions.
 */

sysacct()
{
	extern uchar();
	register struct inode *ip;

	if (suser()) {
		if (u.u_arg[0]==0) {
			if (acctp) {
				plock(acctp);
				if(curract != acbuf)
					wacct(acctp);
				brelse(acctbuf);
				iput(acctp);
				acctp = NULL;
			}
			return;
		}
		if (acctp) {
			u.u_error = EBUSY;
			return;
		}
		if ((ip = namei(&uchar, 0))==NULL)
			return;
		if((ip->i_mode & IFMT) != 0) {
			u.u_error = EACCES;
			iput(ip);
			return;
		}
		acctp = ip;
		acctbuf = getblk(NODEV);
		acbuf = curract = acctbuf->b_addr;
		prele(ip);
	}
}

/*
 * On exit, write a record on the accounting file.
 */
acct()
{
	register struct inode *ip;
	register struct acct *ac;
	register i;

	if ((ip=acctp)==NULL)
		return;
	plock(ip);
	ac = curract;
	for(i = 0; i < DIRSIZ; i++)
		ac->ac_comm[i] = u.u_comm[i];
	ac->ac_time = time;
	ac->ac_utime = u.u_utime;
	ac->ac_stime = u.u_stime;
	ac->ac_etime = etime - u.u_start;
	ac->ac_uid = u.u_ruid;
	if(++curract == acbuf + (512/sizeof(*curract)))
		wacct(ip);
	prele(ip);
}

/*
 * Perform actual writing on accounting file
 */
wacct(iip)
struct inode *iip;
{	register struct inode *ip;
	register i,j;
	char *s;

	ip = iip;
	i = curract;
	j = acbuf;
	s = i - j;
	i = ip->i_size0&0377;
	j = ip->i_size1;
	u.u_offset[0] = i;
	u.u_offset[1] = j;
	u.u_base = acbuf;
	u.u_count = s;
	u.u_segflg = 1;
	u.u_error = 0;
	writei(ip);
	if(u.u_error) {
		ip->i_size0 = i;
		ip->i_size1 = j;
	}
	curract = acbuf;
}
