SysIII/usr/lib/acct/runacct

#       "nitely accounting shell, should be run from cron (adm) at 4am"
#	"does process, connect, disk, and fee accounting"
#	"prepares command summaries"
#	"shell is restartable and provides reasonable diagnostics"
a=/usr/adm
b=acct/nite
c=$a/$b
e=acct/sum
export PATH
PATH=/usr/lib/acct:/bin:/usr/bin:/etc
statefile=${c}/statefile
active=${c}/active
lastdate=${c}/lastdate
errormsg="\n\n\n\n************ ACCT ERRORS --- RUN ABORTED : see  ${active}${d} ************\n\n\n\n"
cd $a
#		"make sure that 2 crons weren't started, or leftover problems"
date  > $b/lock1
chmod 400 $b/lock1
ln $b/lock1 $b/lock
if test $? -ne 0; then
	l="\n\n\n\n*************** 2 CRONS or ACCT PROBLEMS ***************\n\n\n\n"
	(date ; echo "$l" ) >/dev/console
	echo "$l" | mail adm root
	echo "ERROR: locks found, run aborted" >> ${active}
	rm -f ${c}/lock*
	exit 1
fi


case $# in
0)
#	"as called by the cron each day"
	d="`date +%m%d`"
	if test ! -r ${lastdate} ; then
		echo "0000" > ${lastdate}
	fi
	if test "${d}" = "`cat ${lastdate}`"; then
		(date; echo "${errormsg}") > /dev/console
		echo "${errormsg}" | mail root adm
		echo "ERROR: acctg already run for `date`: check ${lastdate}" >> ${active}
		rm -f ${c}/lock*
		mv ${active} ${active}${d}
		exit 1
	fi
	echo ${d} > ${lastdate}
	echo "SETUP" > ${statefile}
	nulladm ${active}
	echo "\n\n\n\n\n**********  SYSTEM ACCOUNTING STARTED `date`  **********\n\n\n\n\n" > /dev/console
	;;

1)
#	"runacct MMDD  (date)  will restart at current state"
	d=$1
	echo "restarting acctg for ${d} at `cat ${statefile}`" >> ${active}
	echo "\n\n\n\n\n********** SYSTEM ACCOUNTING RESTARTED `date` **********\n\n\n\n\n" > /dev/console
	;;

2)
#	"runacct MMDD STATE  restart at specified state"
	d=$1
	echo "restarting acctg for ${d} at $2" >> ${active}
	echo "previous state was `cat ${statefile}`" >> ${active}
	echo "$2" > ${statefile}
	echo "\n\n\n\n\n********** SYSTEM ACCOUNTING RESTARTED `date` **********\n\n\n\n\n" > /dev/console
	;;
*)
	(date; echo "${errormsg}") > /dev/console
	echo "${errormsg}" | mail root adm
	echo "ERROR: runacct called with invalid arguments" > ${active}
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	exit 1
	;;
esac


#	"processing is broken down into seperate, restartable states"
#	"the statefile is updated at the end of each state so that the"
#	"next loop through the while statement switches to the next state"
while [ 1 ]
do
case "`cat ${statefile}`" in
SETUP)

cd $a
(date ; ls -l fee pacct* wtmp* ) >> ${active}

#	"switch current pacct file"
turnacct switch
rc=$?
if test ${rc} -ne 0; then
	(date ; echo "${errormsg}" ) > /dev/console
	echo "${errormsg}" | mail root adm
	echo "ERROR: turnacct switch returned rc=${rc}" >> ${active}
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	exit 1
fi

#	" give pacct files unique names for easy restart "
for i in pacct?
do
	if test -r S${i}.${d} ; then
		 (date ; echo "${errormsg}" ) > /dev/console
		echo "${errormsg}" | mail root adm
		echo "ERROR: S${i}.${d} already exists" >> ${active}
		echo "file setups probably already run" >> ${active}
		rm -f ${c}/lock*
		mv ${active} ${active}${d}
		exit 1
	fi
	mv ${i} S${i}.${d}
done


#	"add current time on end"
if test -r ${b}/wtmp.${d} ; then
	(date ; echo "${errormsg}" ) > /dev/console
	echo "${errormsg}" | mail root adm
	echo "ERROR: ${b}/wtmp.${d} already exists: run setup manually" > ${active}
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	exit 1
fi
cp wtmp ${b}/wtmp.${d}
acctwtmp "" "console" >> ${b}/wtmp.${d}
nulladm wtmp


#	"copy pacct and wtmp files for backup copies"
#	" to be removed after a filesave"
#	"these lines should be commented out if your /usr space is low"
cp ${b}/wtmp.${d} ${e}/wtmp.${d}
cat Spacct?.${d} > ${e}/pacct.${d}



echo "files setups complete" >> ${active}
echo "WTMPFIX" > ${statefile}
;;


WTMPFIX)
#	"verify the integrity of the wtmp file"
#	"wtmpfix will automatically fix date changes"
cd $c
nulladm tmpwtmp wtmperror
wtmpfix < wtmp.${d} > tmpwtmp 2>wtmperror
if test $? -ne 0 ; then
	(date ; echo "${errormsg}") | mail root adm
	echo "${errormsg}" > /dev/console
	echo "ERROR: wtmpfix errors see ${c}/wtmperror${d}" >> ${active}
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	mv wtmperror wtmperror${d}
	exit 1
fi

echo "wtmp processing complete" >> ${active}
echo "CONNECT1" > ${statefile}
;;


CONNECT1)
#	"produce connect records in the ctmp.h format"
#	"the lineuse and reboots files are used by prdaily"
cd $c
nulladm lineuse reboots ctmp log
acctcon1 -t -l lineuse -o reboots < tmpwtmp  2> log |\
sort +1n +2 > ctmp 
if test -s log ; then
	(date ; echo "${errormsg}") | mail adm root
	echo "${errormsg}" > /dev/console
	echo "ERROR: connect acctg failed:  check ${c}/log" >> ${active}
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	mv ${c}/log ${c}/log${d}
	exit 1
fi

echo "CONNECT2" > ${statefile}
;;


CONNECT2)
#	"convert ctmp.h records in tacct records"
cd $c
nulladm ctacct.${d}
acctcon2 < ctmp | acctmerg > ctacct.${d}

echo "connect acctg complete" >> ${active}
echo "PROCESS" > ${statefile}
;;


PROCESS)
#	"correlate Spacct and ptacct files by number"
#	"will not process Spacct file if corresponding ptacct exists"
#	"remove the ptacct file to rurun the Spacct file"
#	"if death occurs here, rerunacct should remove last ptacct file"
cd $c
num=""
for i in 1 2 3 4 5 6 7 8 9
do
	if test -r ${a}/Spacct${i}.${d}; then
		num="${num} ${i}"
	fi
done
for i in ${num}
do
	if test -s ptacct${i}.${d}; then
		echo "WARNING: process acctg already run for Spacct${i}.${d}" >> ${active}
		echo "WARNING: remove ${c}/ptacct${i}.${d} to rerun" >> ${active}
	else
		nulladm ptacct${i}.${d}
                acctprc1 ctmp < ${a}/Spacct${i}.${d} |\
		acctprc2 > ptacct${i}.${d}
		echo "process acctg complete for Spacct${i}.${d}" >> ${active}
	fi
done
echo "all process actg complete for ${d}" >> ${active}
echo "MERGE" > ${statefile}
;;


MERGE)
cd $c
#	"merge ctacct and ptacct files together"
acctmerg ptacct?.${d} < ctacct.${d} > daytacct

echo "tacct merge to create daytacct complete" >> ${active}
echo "FEES" > ${statefile}
;;


FEES)
cd $c
#	"merge in fees"
if test -s $a/fee; then
	cp daytacct tmpdayt
	sort +0n +2 $a/fee | acctmerg -i | acctmerg tmpdayt  > daytacct
	echo "merged fees" >> ${active}
	rm -f tmpdayt
else
	echo "no fees" >> ${active}
fi
echo "DISK" > ${statefile}
;;


DISK)
cd $c
#	"the last act of any disk acct procedure should be to mv its"
#	"entire output file to disktacct, where it will be picked up"
if test -r disktacct; then
	cp daytacct tmpdayt
	acctmerg disktacct  < tmpdayt > daytacct
	echo "merged disk records" >> ${active}
	rm -f tmpdayt disktacct
else
	echo "no disk records" >> ${active}
fi
echo "MERGETACCT" > ${statefile}
;;

MERGETACCT)
cd ${a}/acct
#	"save each days tacct file in sum/tacct.${d}"
#	"if sum/tacct gets corrupted or lost, could recreate easily"
#	"the mounthly acctg procedure should remove all sum/tacct files"
cp nite/daytacct sum/tacct$d
if test ! -r sum/tacct; then
	echo "WARNING: recreating ${a}/sum/tacct " >> ${active}
	nulladm sum/tacct
fi

#	"merge in todays tacct with the summary tacct"
cp sum/tacct sum/tacctprev
acctmerg sum/tacctprev  < sum/tacct$d > sum/tacct

echo "updated sum/tacct" >> ${active}
echo "CMS" > ${statefile}
;;


CMS)
cd ${a}/acct
#	"do command summaries"
nulladm sum/daycms
if test ! -r sum/cms; then
	nulladm sum/cms
	echo "WARNING: recreating ${a}/sum/cms " >> ${active}
fi
cp sum/cms sum/cmsprev
acctcms $a/Spacct?.${d}  > sum/daycms
acctcms -s sum/daycms sum/cmsprev  > sum/cms
acctcms -a -s sum/daycms | sed -n 1,56p  > nite/daycms
acctcms -a -s sum/cms | sed -n 1,56p  > nite/cms
lastlogin 
echo "command summaries complete" >> ${active}
echo "USEREXIT" > ${statefile}
;;


USEREXIT)
#	"any installation dependant accounting programs should be run here"


echo "CLEANUP" > ${statefile}
;;


CLEANUP)
cd ${a}/acct
#	" finally clear files; could be done next morning if desired"
nulladm $a/fee
rm -f ${a}/Spacct?.${d}
#	"put reports onto a file"
prdaily >> sum/rprt$d;
rm -f nite/lock*
rm -f nite/ptacct?.${d} nite/ctacct.${d}
rm -f nite/wtmp.${d} nite/wtmperror${d} nite/active${d}
mv nite/tmpwtmp nite/owtmp
echo "system accounting completed at `date`" >> ${active}
echo "********** SYSTEM ACCOUNTING COMPLETED `date` **********" > /dev/console
echo "COMPLETE" > ${statefile}
exit 0
;;

*)
	(date;echo "${errormsg}") > /dev/console
	echo "${errormsg}" | mail adm root
	echo "ERROR: invalid state, check ${statefile}" >> active
	rm -f ${c}/lock*
	mv ${active} ${active}${d}
	exit 1
	;;
esac
done


#	" runacct is normally called with no arguments from the cron"
#	" it checks its own locks to make sure that 2 crons or previous"
#	" problems have not occured"

#	" runacct uses the statefile to record its progress"
#	" each state updates the statefile upon completion"
#	" then the next loop though the while picks up the new state"

#	" to restart this shell,  check the active file for diagnostics"
#	" fix up any corrupted data (ie. bad pacct or wtmp files)"
#	" if runacct detected the error it removes the locks"
#	" remove the locks if necessary, otherwise runacct will complain"
#	" the lastdate file should be removed or changed"
#	" restart runacct at current state with:  runacct MMDD"
#	" to override the statefile: runacct MMDD STATE"


#	" if runacct has been executed after the latest failure"
#	" ie. it ran ok today but failed yesterday"
#	" the statefile will not be correct"
#	" check the active files and restart properly"

#	" if runacct failed in the PROCESS state, remove the last"
#	" ptacct file because it may not be complete"

#	" if shell has failed several days, do SETUP manually"
#	" then rerun runacct once for each day failed"
#	" could use fwtmp here to split up wtmp file correctly"

#	" normally not a good idea to restart the SETUP state"
#	" should be done manually, or just cleanup first"


#	" FILE USAGE:	all files in /usr/adm/ac/nite unless specified"

#	" statefile	records progess of runacct"
#	" lastdate	last day runacct ran in date +%m%d format"
#	" lock lock1	controls serial use of runacct"
#	" active	place for all descriptive and error messages"
#	" fd2log	fd2 output for runacct ( see cron entry ) "
#	" wtmp.MMDD owtmp yesterdays wtmp file"
#	" tmpwtmp	yesterdays wtmp corrected by wtmpfix"
#	" wtmperror	place for wtmpfix error messages"
#	" lineuse	lineusage report used in prdaily"
#	" reboots	reboots report used in prdaily"
#	" ctmp	ctmp.h records from acctcon1"
#	" log		place for error messages from acctcon1"
#	" ctacct.MMDD	connect tacct records for MMDD"
#	" ptacct.n.MMDD	process tacct records n files for MMDD"
#	" daytacct	total tacct records for this days accounting"
#	" disktacct	disk tacct records produced by disk shell"
#	" daycms	ascii daily command summary used by prdaily"
#	" cms		acsii total command summary used by prdaily"

#	" following files in /usr/adm directory"

#	" fee		output from chargefee program"
#	" pacct		active pacct file"
#	" pacctn	switched pacct files"
#	" Spacctn.MMDD	pacct files for MMDD after SETUP state"
#	" wtmp		active wtmp file"

#	" following files in /usr/adm/acct/sum"

#	" loginlog	output of lastlogin used in prdaily"
#	" tacct		total tacct file for current fiscal"
#	" tacct.MMDD	tacct file for day MMDD"
#	" cms		total cms file for current fiscal"
#	" rprt.MMDD	output of prdaily program"
#	" wtmp.MMDD	saved copy of wtmp for MMDD"
#	" pacct.MMDD	concatenated version of all pacct files for MMDD"
#	" cmsprev	total cms file without latest update"
#	" tacctprev	total tacct file without latest update"
#	" daycms	cms files for todays usage"