#!/bin/perl 
# (C)  Copyright 1993 Rahul Dhesi, All Rights Reserved
# ... except that permission is granted for copying and creation
# of derivative works under the same conditions as perl.

# $Header: /local/undoc/RCS/wtrim,v 1.13 1993/07/09 15:41:58 dhesi Exp $

# Trim the wtmp file to hold a specified number of records.
# This script is offered "as is", though it appears to work under SunOS 4.1.  
#
# <1>	Rahul Dhesi <dhesi@rahul.net>
# <2>	dhesi@cirrus.com
# <3>	cmc@srg-ssr.ch  	solaris hacks
# <4>	sean@ch.swissbank.com 	Added comments/tabs

# CAVEATS:
# 1. There are two race conditions; one is minimized by creating an
#    /etc/nologin file, whose creation causes the second race condition.
#    Search for 'RACE CONDITION'.
# 2. There is no check for the filesystem filling up while a temporary
#    copy of the wtmp file is made.

$myname = "wtrim.pl";
$default = "/var/adm/[wu]tmp[x]";

if (@ARGV != 2) {
   print <<EOF;
usage:  wtrim file count 

where file is:
	wtmp			(SunOS 5.x, SunOS 4.x)
	wtmpx			(SunOS 5.x)
	utmp			(SunOS 5.x)
	utmpx			(SunOS 5.x)

Approximately specified number (count) of records, taken from the 
end of $default are saved, 
and preceding records are trimmed.

The original $default file is renamed to $default.old.

Block size is calculated automatically from file name.
EOF
exit(0);
}

$wname = $ARGV[0];
$wanted = $ARGV[1];			# how many records we want
#printf("%s\n", $wname);

# pathnames -- adjust as needed
$dd  = "/usr/bin/dd";			# pathname of 'dd' program
$WTMP = "/var/adm/$wname";		# wtmp log file
$OLD_WTMP = "$WTMP.old";		# will save current wtmp here
$NEW_WTMP = "$WTMP.new.$$";		# new wtmp; will get renamed to $WTMP
$nologin = "/etc/nologin";		# for disabling logins
$nologin_new = "$nologin.new.$$";	# temp; will get renamed to $nologin

# scale factor, for using bigger block size than the native wtmp block size
$scale = 1000;

#printf("%s\n",$NEW_WTMP);

if ( $wname eq "wtmp" || $wname eq "utmp" ) {
	$bs = 36;			# size of wtmp record in bytes
} elsif ( $wname eq "wtmpx" || $wname eq "utmpx" ) {
	$bs = 372;			# size of wtmp record in bytes
} else {
	&exit("$myname: error: file unkown can't set block size: $!\n");
}

#printf("%d\n",$bs);

$tot_recs = (-s $WTMP) / $bs;		# total no. of records in log file
$skip = $tot_recs  - $wanted;		# records to skip
if ($skip < 0) {
   $skip = 0;
}

# Now we speed things up a little by scaling up the block size.  We may end
# up trimming a slightly fewer blocks.
if ($tot_recs > $bs * $scale) {
   $bs *= $scale;
   $skip = int ($skip / $scale);
}

# delete first to save disk space
unlink $OLD_WTMP;
# disable logins (just for a second)
if (! -e $nologin) {
   open (NOLOGIN, ">$nologin_new") ||
      &exit("$myname: error: can't write to $nologin_new: $!\n");
   print NOLOGIN <<EOF;
*************************************************
SYSTEM RECONFIGURATION -- TRY AGAIN IN ONE MINUTE
*************************************************
EOF
   close(NOLOGIN);
   if (! -e $nologin) {			# RACE CONDITION
      $disabled = 1;
      rename ($nologin_new, $nologin);
   } else {
      unlink $nologin_new;
   }
}
# get needed records
system "$dd if=$WTMP bs=$bs skip=$skip >$NEW_WTMP 2>/dev/null";
# RACE CONDITION
link ($WTMP, $OLD_WTMP) || &exit("$myname: error: link failed: $!\n");
rename($NEW_WTMP, $WTMP) || &exit("$myname: error: rename failed: $!\n");

&exit();

sub exit {
   local($msg) = @_;
   # re-enable logins
   $disabled && unlink $nologin;
   unlink $NEW_WTMP;
   unlink $nologin_new;
   if ($msg) {
      print $msg;
      exit(1);
   }
   exit(0);
};

# END


