# HG changeset patch # User Tero Marttila # Date 1206057231 -7200 # Node ID 6a49fc285842d2bcc8023b1794f3f8649e7046cb # Parent 614161f85d9b1f5a07cd0e91210eb31778756104 C module to handle utmp entires committer: Tero Marttila diff -r 614161f85d9b -r 6a49fc285842 _utmp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_utmp.c Fri Mar 21 01:53:51 2008 +0200 @@ -0,0 +1,57 @@ +#include + +#include + +#include + +PyObject *parse (PyObject *self, PyObject *args) { + char *bytes; + size_t size; + + struct utmp *item; + + /* not unicode */ + if (!PyArg_ParseTuple(args, "t#", &bytes, &size)) + return NULL; + + if (size != sizeof(struct utmp)) { + PyErr_SetString(PyExc_ValueError, "given buffer is of the wrong length"); + return NULL; + } + + item = (struct utmp *) bytes; + + /* parse utmp from bytes to result */ + return Py_BuildValue("hIs#s#s#s#(hh)i(ii)s#", + item->ut_type, item->ut_pid, + item->ut_line, sizeof(item->ut_line), + item->ut_id, sizeof(item->ut_id), + item->ut_user, sizeof(item->ut_user), + item->ut_host, sizeof(item->ut_host), + item->ut_exit.e_termination, item->ut_exit.e_exit, + item->ut_session, + item->ut_tv.tv_sec, item->ut_tv.tv_usec, + item->ut_addr_v6, sizeof(item->ut_addr_v6) + ); +} + +PyObject *size (PyObject *self, PyObject *args) { + /* return the size of an UTMP struct */ + + if (!PyArg_ParseTuple(args, "")) + return NULL; + + return PyInt_FromSsize_t(sizeof(struct utmp)); +} + +static PyMethodDef module_methods[] = { + {"parse", parse, METH_VARARGS, "parse a utmp struct from a byte string"}, + {"size", size, METH_VARARGS, "return the size of an utmp record in bytes"}, + {NULL} +}; + +PyMODINIT_FUNC init_utmp(void) { + PyObject *m; + + m = Py_InitModule3("_utmp", module_methods, "utmp struct parsing"); +} diff -r 614161f85d9b -r 6a49fc285842 setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Fri Mar 21 01:53:51 2008 +0200 @@ -0,0 +1,10 @@ +from distutils.core import setup, Extension + +_utmp = Extension('_utmp', sources=['_utmp.c']) + +setup( + name = "FixBot", + version = "0.1", + description = "IRC bot for sysadmin things", + ext_modules = [_utmp], +) diff -r 614161f85d9b -r 6a49fc285842 utmp.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utmp.py Fri Mar 21 01:53:51 2008 +0200 @@ -0,0 +1,50 @@ +import socket + +import _utmp + +class WtmpEntry (object) : + _ATTRS = ( + "type", "pid", "line", "id", "user", "host", "exit", "session", "tv", "addr_v6" + ) + + def __str__ (self) : + return " ".join("%s=%s" % (key, getattr(self, key)) for key in self._ATTRS) + +def read_entry (file) : + bytes = file.read(_utmp.size()) + + if not bytes : + return + + result = _utmp.parse(bytes) + + wtmp = WtmpEntry() + + for name, field in zip(wtmp._ATTRS, result) : + if isinstance(field, str) and name not in ("addr_v6", ) : + field = field.rstrip("\0") + + setattr(wtmp, name, field) + + wtmp.addr_v6 = socket.inet_ntop(socket.AF_INET6, wtmp.addr_v6) + + return wtmp + +def read_entries (file) : + while True : + wtmp = read_entry(file) + + if wtmp : + yield wtmp + else : + return + +def test_main () : + fh = open("/var/log/wtmp", "r") + + for item in read_entries(fh) : + print item + +if __name__ == '__main__' : + test_main() +