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

F

Fredrik Normann

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.

Best regards,
-fredrik-normann-
 
F

Fredrik Normann

Fredrik said:
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.

A friend of mine made this C-program, that does the trick :)

#include <protocols/rwhod.h>
#include <stdio.h>
#include <unistd.h>
#include <strings.h>

#include <time.h>
#include <sys/time.h>

#include <sys/types.h>
#include <netinet/in.h>
#include <inttypes.h>

#ifdef SOL
#include <stddef.h>
#else
#include <linux/stddef.h>
#endif

int main (int argc, char **argv)
{

char *filename, *binary;
FILE *fp;
struct whod entry;
struct outmp who;
size_t ret;
size_t cnt = 0;
char *user = (char*) malloc (8);
char *timestr = (char*) malloc (512);
char *hostname = (char*) malloc (512);
int hostlen, ulen;
size_t prefix, we_len;

hostlen = 0;
ulen = 0;

struct timeval now;
struct tm *tptr;
time_t t;

binary = *argv;
ret = gettimeofday (&now, 0);
if (ret < 0) {
perror ("Error getting time of day");
exit (2);
}

if (argc < 2) {
printf ("%s: ERROR, no whod file specified\n", binary);
exit (1);
}

filename = *(argv + 1);

fp = fopen (filename, "r");
if (fp == NULL) {
perror ("Error opening file");
exit (3);
}

#ifdef SOL
ret = fread (&entry, 1, sizeof (entry), fp);
#else
ret = fread_unlocked (&entry, 1, sizeof (entry), fp);
#endif
if (ret < 0) {
perror ("Error reading file");
exit (4);
}

prefix = offsetof (struct whod, wd_we) / sizeof (struct whoent);
we_len = ret / sizeof (struct whoent) - prefix;

/* Find lengths of strings */
for (cnt = 0; cnt < we_len; cnt++) {
who = entry.wd_we[cnt].we_utmp;
strncpy (user, who.out_name, 8);
if (strlen (user) > ulen)
ulen = strlen (user);
if ((strlen (entry.wd_hostname) + strlen (who.out_line) + 1) > hostlen)
hostlen = strlen (entry.wd_hostname) + strlen (who.out_line) + 1;
}

for (cnt = 0; cnt < we_len; cnt++) {
who = entry.wd_we[cnt].we_utmp;
strncpy (user, who.out_name, 8);
strncpy (hostname, entry.wd_hostname, 512);
strcat (hostname, ":");
strncat (hostname, who.out_line, 8);

t = now.tv_sec - ntohl (entry.wd_we[cnt].we_idle);

entry.wd_we[cnt].we_idle = ntohl (entry.wd_we[cnt].we_idle) / 60;

printf ("%-*s %-*s",
ulen, user,
hostlen, hostname);
if (entry.wd_we[cnt].we_idle >= 0) {
tptr = localtime (&t);
strftime (timestr, 512, "%a %b %d %H:%m", tptr);

printf (" %s ", timestr);
printf ("%5d:%02d",
entry.wd_we[cnt].we_idle / 60,
entry.wd_we[cnt].we_idle % 60);
}
printf ("\n");
}

fclose (fp);
}
 
D

Dennis Lee Bieber

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?

--
 
F

Fredrik Normann

Dennis said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top