#!/usr/bin/perl

open (LASTLOG, "< /usr/adm/lastlog")	|| die "can't open /usr/adm/lastlog: $!";

$lastlog_t = 'L A8 A16';
$lastlog_s = length(pack($lastlog_t, ()));
# struct lastlog {
#         time_t  ll_time;
#         char    ll_line[8];
#         char    ll_host[16];            /* same as in utmp */
# };

if (!@ARGV) {
    for ( $uid = 0;
	  sysread(LASTLOG, $buff, $lastlog_s) == $lastlog_s;
	  $uid++
	)
    {
	next unless @p = getpwuid($uid);
	($time, $line, $host) = unpack($lastlog_t, $buff);
	$uid = $p[2];
	$user = $p[0];
	$uid{$user} = $uid;

	###  print STDERR "read $user\n";

	$time{$user} = $time || 0;
	$line{$user} = $line || '';
	$host{$user} = $host || '';
    }

    for $user ( sort { $time{$a} <=> $time{$b} || $uid{$a} <=> $uid{$b} } keys %time ) {
	$uid = $uid{$user};
	$time = $time{$user};
	$line = $line{$user};
	$host = $host{$user};
	write;
    } 

} 

USER: foreach $user ( @ARGV ) {
    if ($user =~ /^\d+$/) {
	unless (@p = getpwuid($user)) { warn "no such uid $user\n"; next; }
	$user = $p[0];
	$uid = $p[2];
    } elsif (!defined ($uid = getpwnam($user))) { warn "no user $user\n"; next; } 
    seek(LASTLOG, $uid * $lastlog_s, 0) or die "seek failed: $!";
    ($time, $line, $host) = sysread(LASTLOG, $buff, $lastlog_s) == $lastlog_s
		    ? unpack($lastlog_t, $buff)
		    : ();
    write;
} 

format STDOUT_TOP = 
@<<<<<<<  @>>>>> @<<<<<<< @<<<<<<<<<<<<<<<<<< @*
'user', 'uid', 'line', 'host', 'when'
--------  ------ -------- ------------------- -----------------------
.

format STDOUT = 
@<<<<<<<  @>>>>> @<<<<<<< @<<<<<<<<<<<<<<<<<< @*
$user, $uid, $line, $host, $time ? scalar localtime $time : "[ never logged in ]"
.