Searching the output of last

Raymond Chen raymond at math.berkeley.edu
Mon Apr 29 15:37:21 AEST 1991


In article <1991Apr29.043041.20454 at casbah.acns.nwu.edu>, navarra at casbah (John 'tms' Navarra) writes: 

>how bout setting up a program that... looks thru utmp by doing a last
>| grep time (might be slow) ... then increments it by one for interval loops.
              ^^^^^^^^^^^^^
              my vote for understatement of the day.  It is not unheard
of for people to be logged in for days at a time.  Incrementing by one means
you have to perform thousands of greps.

[For comp.lang.perlers, the problem is to write a progral called `whenwho'
which prints out everybody who was logged on at the time indicated on the
command line.]

Try this.  Hacked up in 15 minutes, minimally tested.  Part of the
problem is that you never know if you've searched backwards far
enough, because there might be someone who has been logged on
continuously for the past five months.  In the original problem,
however, we are told that the wtmp goes back only as far as around 5am
the day of the run, so this isn't an issue.

#!/bin/perl
# fetch desired time
die "usage:  whenwho hh:mm\n" 
  if (($hr, $min) = $ARGV[0] =~ /^(\d+):(\d+)$/) != 2;

# compute the human-readable time into a UNIX time thingie
$now = time; @now = localtime($now);
$midnight = $now - 3600*$now[2] - 60*$now[1] - $now[0]; #midnight today
$desired = $midnight + 3600*$hr + 60*min;               #time we want

# prepare to read the wtmp
$wtmp = "A8 A8 A16 l"; $size = length(pack($wtmp, "", "", "", 0));
$pos = -$size;
open(U, "/usr/adm/wtmp") || die "Yow!  /usr/adm/wtmp: $!\n";

# go for it!  Seek backwards through the wtmp.
while (seek(U, $pos, 2)) { read(U, $_, $size); $pos -= $size;
  ($line, $name, $host, $time) = unpack($wtmp, $_); # get wtmp
  if ($name) { # somebody logged in
  if ($time < $desired && $desired < $line{$line}) { # got one!
    printf "%8s %8s\n", $line, $name;
  } } else { $line{$line} = $time; } #logged out; remember logout time
}
__END__
Of course, Randal probably could do this in one line :-)

print sort "another p", "Just ", "hacker,", "erl ";



More information about the Comp.unix.questions mailing list