Reading files in /var/spool/rwho/whod.*

Fredrik Normann fredrin at ifi.uio.no
Thu Jun 30 04:57:16 EDT 2005


Dennis Lee Bieber wrote:
> On Mon, 27 Jun 2005 13:26:12 +0200, Fredrik Normann <fredrin at ifi.uio.no>
> declaimed the following in comp.lang.python:
> 
> 
>>Hello,
>>
>>I'm trying to read the binary files under /var/spool/rwho/ so I'm wondering if 
>>anyone has done that before or could give me some clues on how to read those 
>>files. I've tried to use the binascii module without any luck.
>>
> 
> 	Have you looked at the struct module?
> 

Thanks for the tip. A friend of mine helped me with making this small script:


#!/usr/bin/env python

"""whod file parser.

Made by: Igor V. Rafienko

This tiny script tries to grock whod files.
"""


from struct import calcsize, unpack, pack
from socket import ntohl
import time





outmp_format = '8s8s4s'
whoent_format = '%ds4s' % calcsize(outmp_format)
almost_whod = 'cc2s4s4s32s12s4s'


def make_string(s):
     """Stupid C. Chop the string off at the first '\0'."""

     index = s.find('\0')
     if index != -1:
         return s[:index]
     # fi
# end make_string


def make_time(seconds):
     """Convert from seconds since Epoch to ISO8601."""

     return time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(seconds))
# end make_time


def make_int(binary):
     """Convert binary from network representation to host int."""

     assert len(binary) == 4, "ints are 4 bytes long here"

     if calcsize("i") == 4:
         return ntohl(unpack("i", binary)[0])
     elif calcsize("l") == 4:
         return ntohl(unpack("l", binary)[0])
     else:
         raise "Dammit! no suitable integral type"
     # fi
# end make_int


def parse_one_outmp(binary_data):
     """Parse an outmp struct."""

     out_line, out_name, out_time = unpack(outmp_format, binary_data)
     out_time = make_int(out_time)

     return out_line, out_name, out_time
# end parse_one_outmp


def parse_one_whoent(binary_data):
     """Parse a whoent struct."""

     outmp_part, we_idle = unpack(whoent_format, binary_data)

     we_idle = make_int(we_idle)
     out_line, out_name, out_time = parse_one_outmp(outmp_part)

     return out_line, out_name, out_time, we_idle
# end parse_one_whoent


def parse_one_file(binary_data):
     """Parse the entire thing."""

     # First we parse everything, except for the whoent-array
     prefix = unpack(almost_whod, binary_data[:calcsize(almost_whod)])

     print "prefix has %d elemenets" % len(prefix)
     print "wd_vers:", ord(prefix[0])
     print "wd_type:", ord(prefix[1])
     print "wd_fill:", make_string(prefix[2])
     print "wd_sendtime:", make_time(make_int(prefix[3]))
     print "wd_recvtime:", make_time(make_int(prefix[4]))
     print "wd_host: ", make_string(prefix[5])
     load = prefix[6]
     print "wd_load avg: %d, %d, %d" % tuple([make_int(x) for x in
                                           (load[:4], load[4:8], load[8:])])
     print "wd_boottime", make_time(make_int(prefix[7]))

     sz = calcsize(whoent_format)
     array_data = binary_data[calcsize(almost_whod):]
     assert len(array_data) % sz == 0, "Aiee! corrupt chunk?"
     whoent_chunks = [ array_data[sz*x:sz*(x+1)] for x in range(len(array_data) 
/ sz) ]
     print "%d whoent chunks" % len(whoent_chunks)

     for out_line, out_name, out_time, we_idle in [parse_one_whoent(x)
                                                   for x in whoent_chunks]:
         print "\tout_line:", make_string(out_line)
         print "\tout_name:", make_string(out_name)
         print "\tout_time:", make_time(out_time)
         print "\twe_idle:", we_idle
     # od
# end parse_one_file



More information about the Python-list mailing list