Xref: utzoo comp.unix.questions:30827 comp.lang.perl:5115 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!uunet!stanford.edu!agate!sunkist.berkeley.edu!raymond From: raymond@math.berkeley.edu (Raymond Chen) Newsgroups: comp.unix.questions,comp.lang.perl Subject: Re: Searching the output of last Keywords: last awk sed perl C whatever Message-ID: <1991Apr29.053721.8733@agate.berkeley.edu> Date: 29 Apr 91 05:37:21 GMT References: <1991Apr28.070748.5279@bradley.bradley.edu> <1991Apr29.021236.12132@casbah.acns.nwu.edu> <1991Apr29.040325.1822@athena.mit.edu> <1991Apr29.043041.20454@casbah.acns.nwu.edu> Sender: root@agate.berkeley.edu (Charlie Root) Reply-To: raymond@math.berkeley.edu (Raymond Chen) Organization: U.C. Berkeley Lines: 47 In-Reply-To: navarra@casbah.acns.nwu.edu (John 'tms' Navarra) Originator: raymond@sunkist.berkeley.edu In article <1991Apr29.043041.20454@casbah.acns.nwu.edu>, navarra@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 ";