dsheroh has asked for the wisdom of the Perl Monks concerning the following question:
I've written a set of utilities to do some per-host auditing of inactive user accounts. User activity is determined based on parsing each host's wtmp file1 using read and unpack2. Determining the wtmp formats in use took a little trial and error, but I quickly had it working properly on a test host.
Then I sent it off to some other hosts for further testing and it all fell apart...
Minimal test code to demonstrate how I'm parsing wtmp:
#!/usr/bin/perl -w use strict; my $wtmp_fmt = 'x44 A32 x264 l x40'; open(WTMP, './wtmp') || die "Unable to open wtmp file: $!\n"; my $rec; my $rec_size = length pack ($wtmp_fmt, ()); my $reccount = 0; while (read(WTMP, $rec, $rec_size)) { $reccount++; print length $rec, ' - '; if (length $rec < $rec_size) { print "<incomplete record>\n"; last; } my @data = unpack($wtmp_fmt, $rec); my $name = $data[0] || '<no name>'; my $logtime = localtime($data[1]) || '<no time>'; print "$name\tat $logtime\n"; } close WTMP; print "$reccount records read\n";
And some sample output, generated using identical copies of a single wtmp file:
The original development host, running Red Hat AS4 with perl-5.8.5-12:
384 - root at Wed May 3 11:42:48 2006 384 - <no name> at Wed May 3 11:42:49 2006 384 - admin_esper at Mon May 8 13:01:38 2006 384 - <no name> at Mon May 8 13:01:40 2006 384 - root at Mon May 8 14:45:49 2006 ... 384 - root at Mon May 22 10:15:37 2006 108 records read
The initial problem host, running Red Hat AS3 with perl-5.8.0-90.4:
384 - root at Wed May 3 11:42:48 2006 384 - <no name> at Fri Jan 2 00:59:44 1970 384 - sper^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@smspap1 at Tu +e Oct 26 10:21:36 1999 384 - <no name> at Wed Dec 31 18:00:00 1969 384 - ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@smspap100l.xxxxxx at Wed Dec 31 +18:00:00 1969 ... 384 - }í at Wed Dec 31 18:00:00 1969 79 - <incomplete record> 108 records read
And an HP-UX host, also running Perl 5.8.0, binary build 806 for PA-RISC from ActiveState:
384 - root at Thu Aug 30 22:55:32 1906 384 - <no name> at Wed Mar 13 03:15:48 1907 384 - admin_esper at Sat Apr 18 15:48:52 1903 384 - <no name> at Wed May 11 00:29:24 1904 384 - root at Fri Mar 25 04:51:48 1960 ... 384 - root at Wed Sep 8 00:48:36 1915 108 records read
(Note that the mangled dates in the HP-UX output are expected, due to PA-RISC having a different endianness than x86.)
Testing on other machines, correct results (modulo endianness problems in the date) are consistently obtained on Red Hat with 5.8.5 and HP-UX with 5.8.0, but consistently mangled on Red Hat with 5.8.0, builds 88.9 and 90.4 (the only RH 5.8.0 builds in use here). The mangled parsing appears to stem from read() consuming more than 384 bytes per read (generally in the range of 387-394), but it does so in a deterministic fashion - the mangled results are always identical across all affected hosts.
So... Are there any known (or suggested) workarounds for this, within the confines of a change management policy which prevents an upgrade to a newer version of perl at this time?
Footnotes:
2 I am aware of at least one CPAN module which parses wtmp, but it is not usable in this case due to a combination of technical and procedural factors.
Update: Looks like it was caused by data being incorrectly parsed as unicode by read. I've changed the open call to open(WTMP, '<:raw', './wtmp') and it now works correctly.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Possible issue with read() in (some builds of) 5.8.0?
by BrowserUk (Patriarch) on May 22, 2006 at 16:29 UTC | |
by dsheroh (Monsignor) on May 22, 2006 at 18:13 UTC | |
by BrowserUk (Patriarch) on May 22, 2006 at 20:02 UTC | |
by dsheroh (Monsignor) on May 22, 2006 at 20:34 UTC |