#/usr/bin/perl # A lastlog record format for use by pack and unpack. $lastlog_t = "L a8 a16"; # (Your machine's may differ.) # Find the length of the fixed-length record. $LEN = length(pack($lastlog_t, 0, '', '')); # Open the database of last logins. Fixed length records. open(LASTLOG, "/usr/adm/lastlog") || die "Can't open lastlog file: $!\n"; # Open the database of accounts. Variable length records. open(PASSWD, "/etc/passwd") || die "Can't open passwd file: $!\n"; # So we can look up month names later. @month = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec); # Now we iterate through variable length records by using # the <> input symbol. In this particular database, the # delimiter just happens to be \n. How lucky can you get? while ($varrec = ) { # And the field delimiter happens to be a colon. Amazing! ($login, $pass, $uid, $gid, $gcos) = split(/:/, $varrec); # Extract name from gcos field portably. $fullname = $gcos; $fullname =~ s/^[^,]*-(.*)\(.*/$1/ || $fullname =~ s/,.*//; if ($fullname =~ /&/) { # You don't want to know. $name = $login; substr($name,0,1) =~ tr/a-z/A-Z/; $fullname =~ s/&/$name/; } # Now we random access the lastlog database. It's keyed # by position based on the user id we want to look up. # Note that we multiply by the record length, since Unix # always wants byte offsets. seek(LASTLOG, $uid * $LEN, 0); read(LASTLOG, $lastlog, $LEN); # Now that we've fetched the lastlog record, we can # break it out into its fields. Note that variable- # length fields above are separated with the split # operator, while these fixed-length fields are separated # using unpack. ($time, $line, $host) = unpack($lastlog_t, $lastlog); # Now remember it so we can sort easily. push(@records, "$time:$login:$uid:$fullname"); } # Now sort the records, oldest first. See the # "numerically" subroutine below. @records = sort numerically @records; foreach $record (@records) { ($time,$login,$uid,$fullname) = split(/:/, $record); # Break out the login time, stored as seconds since # January 1, 1970, into normal date numbers. if ($time) { ($sec,$min,$hour,$mday,$mon,$year) = localtime($time); $year += 1900; $date = "$mday $month[$mon] $year"; } else { $date = "Never"; } # Write using the format below. write; } sub numerically { $a <=> $b; } format top = Uid Login Full Name Last Login . format STDOUT = @>>>> @<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @|||||||||| $uid, $login, $fullname, $date .