manage the wtmp file

Here's a usefull perl script to trim the wtmp file,
in case it got too big, which happens sometimes, or got curropted (which also happens often).
You could learn from here how to parse the wtmp file...
but of course for just reading its content always simply use "last" like Neo said....

Hezki

#!/usr/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