Article 9947 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:9947
Path: feenix.metronet.com!news.utdallas.edu!corpgate!bnrgate!bnr.co.uk!uknet!pipex!howland.reston.ans.net!europa.eng.gtefsd.com!MathWorks.Com!transfer.stratus.com!noc.near.net!newshost.meiko.com!not-for-mail
From: mike@meiko.com (Mike Stok)
Newsgroups: comp.lang.perl
Subject: Re: analyzing /var/adm/lastlog
Date: 19 Jan 1994 16:26:49 -0500
Organization: Meiko Scientific, Inc., MA
Lines: 61
Message-ID: <2hk8ip$qb@burns.meiko.com>
References: <1994Jan19.143326.11913@elsevier.nl>
NNTP-Posting-Host: burns.meiko.com
Keywords: lastlog, reading with Perl

In article <1994Jan19.143326.11913@elsevier.nl>,
Nico Poppelier <n.poppelier@elsevier.nl> wrote:
>How do you analyze /var/adm/lastlog -- lastlog is the file
>that keeps track of the most recent login of every user on
>a Unix system, and /var/adm is where this file is stored
>in SunOS 4.1.x operating systems -- with a Perl program?
>
>I know that you need to an lseek using an offset that is 
>related to the uid of a user, and that every record in the
>file consists of {long, char[8], char[16]}, so I've tried to
>accomplish this with seek and read, but without success.
>
>Has anyone already done this or can anyone provide pointers?

You can use seek & read to position the file & read a buffer of data, and 
then unpack to unpack the data into perl variables...

This runs through the lastlog file on my Sun 4 running SunOS 4.1.3 OK:

#!/usr/bin/perl -w

require 'ctime.pl';

$utSize = 28;
$utTemplate = 'l A8 A16';
$utBuffer = ' ' x $utSize;

$uid = 0;
open (LASTLOG, '</var/adm/lastlog') || die "can't open lastlog ($!)\n";
while (sysread (LASTLOG, $utBuffer, $utSize) == $utSize)
{
  ($time, $line, $host) = unpack ($utTemplate, $utBuffer);

  if ($time != 0)
  {
    $user = (getpwuid ($uid))[0];
    print "$user on $line ";
    print $host eq '' ? "(local)" : "from $host";
    print " at ", &ctime ($time);
  }
  $uid++;
}
close (LASTLOG) || die "can't close lastlog ($!)\n";

I prefer sysread to read, but it doesn't make any difference which you 
use here (but syswrite and write are different...).  If you had a 
particular uid then you can just do something like:

seek (LASTLOG, $uid * $utSize, 0) || die "seek failed ($!)\n";
read (LASTLOG, $utBuffer, $utSize) == $utSize || die "bad read\n";
($time, $line, $host) = unpack ($utTemplate, $utBuffer);

Hope this helps,

Mike

-- 
The "usual disclaimers" apply.    | Meiko
Mike Stok                         | 130C Baker Ave. Ext
Mike.Stok@meiko.concord.ma.us     | Concord, MA 01742
Meiko tel: (617) 890 7676         | 


Article 9950 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:9950
Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!howland.reston.ans.net!pipex!uunet!vtserf.cc.vt.edu!solaris.cc.vt.edu!ceharris
From: ceharris@vt.edu (Carl Harris)
Newsgroups: comp.lang.perl
Subject: Re: analyzing /var/adm/lastlog
Date: 19 Jan 1994 22:18:37 GMT
Organization: VPI & SU (Virginia Tech)
Lines: 20
Message-ID: <2hkbjt$srd@solaris.cc.vt.edu>
References: <1994Jan19.143326.11913@elsevier.nl>
Reply-To: ceharris@vt.edu
NNTP-Posting-Host: mal9000.async.vt.edu
X-Newsreader: TIN [version 1.2 PL2]

Nico Poppelier (nico@elsevier.nl) wrote:
: I know that you need to an lseek using an offset that is 
: related to the uid of a user, and that every record in the
: file consists of {long, char[8], char[16]}, so I've tried to
: accomplish this with seek and read, but without success.

If you're getting garbage when you unpack from the reads, it likely means
that you've got alignment problems.  i.e. there may be padding bytes in-
between fields to force a particular alignment, so that a given field in the
record doesn't necessarily follow at the next physical offset following a 
preceding field.  Scan the file carefully using a hexadecimal/character dump
can usually give you clues as to the physical layout of the fields.

I had this same problem trying to read the auth database in Ultrix.

--
Carl Harris
CSUGRAD Administrator
ceharris@vt.edu
URL = http://csugrad.cs.vt.edu/aboutus/ceharris.html


Article 9979 of comp.lang.perl:
Xref: feenix.metronet.com comp.lang.perl:9979
Path: feenix.metronet.com!news.utdallas.edu!corpgate!bnrgate!bnr.co.uk!pipex!howland.reston.ans.net!vixen.cso.uiuc.edu!moe.ksu.ksu.edu!cbs.ksu.ksu.edu!news
From: Steve Davis <strat@cis.ksu.edu>
Newsgroups: comp.lang.perl
Subject: Re: analyzing /var/adm/lastlog
Date: 20 Jan 1994 11:55:15 -0600
Organization: Kansas State University
Lines: 52
Sender: strat@cbs.ksu.ksu.edu (Steve Davis)
Message-ID: <2hmgi3INN1c1@cbs.ksu.ksu.edu>
References: <1994Jan19.143326.11913@elsevier.nl>
Reply-To: strat@cis.ksu.edu (Steve Davis)
NNTP-Posting-Host: cbs.ksu.ksu.edu
Keywords: lastlog, reading with Perl

n.poppelier@elsevier.nl writes:
:How do you analyze /var/adm/lastlog -- lastlog is the file
:that keeps track of the most recent login of every user on
:a Unix system, and /var/adm is where this file is stored
:in SunOS 4.1.x operating systems -- with a Perl program?

This code was posted recently:

#!/usr/local/bin/perl

# month names for common usage

@months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
           'Sep', 'Oct', 'Nov', 'Dec');

$oneyear = 60*60*24*365.24/2;

setpwent;
while (($name, $junk, $uid) = getpwent) {
        $names{$uid} = $name;
}
endpwent;

open(LASTL,'/var/adm/lastlog');

for ($uid = 0; read(LASTL, $record, 28); $uid++) {
    ($time, $line, $host) = unpack('l A8 A16', $record);
    next unless $time;

    $host = "($host)" if $host;
    ($sec, $min, $hour, $mday, $mon, $year) = localtime($time);

    if (time - $time > $oneyear) {
        printf "%-9s%-8s%s %2d %4d    %s\n",
            $names{$uid}, $line, $months[$mon], $mday, 1900+$year, $host;
    } else {
        printf "%-9s%-8s%s %2d %02d:%02d   %s\n",
            $names{$uid}, $line, $months[$mon], $mday, $hour, $min, $host;
    }
}   

:I know that you need to an lseek using an offset that is 
:related to the uid of a user, and that every record in the
:file consists of {long, char[8], char[16]}, so I've tried to
:accomplish this with seek and read, but without success.

Sounds like an alignment problem.  Good luck!
-- 
                                               Steve Davis (strat@cis.ksu.edu)
                                                       Kansas State University

"What is truth? I don't know and I'm sorry I brought it up." -- Edward Abbey


