fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
authorTero Marttila <terom@paivola.fi>
Fri, 21 Mar 2008 02:37:33 +0200
changeset 11 2d33d62cd8f8
parent 10 687b797f709c
child 12 cf388baabf0a
fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc

committer: Tero Marttila <terom@paivola.fi>
utmp.py
--- a/utmp.py	Fri Mar 21 02:06:52 2008 +0200
+++ b/utmp.py	Fri Mar 21 02:37:33 2008 +0200
@@ -1,10 +1,24 @@
+from twisted.internet import protocol, reactor
+from twisted.python import log
 import socket, os, time
 
-import _utmp
+import _utmp, api, sys
+
+POLL_INTERVAL = 5
+
+def getPidCmd (pid) :
+    try :
+        fh = open("/proc/%d/cmdline" % pid, "r")
+        cmdline = fh.read()
+        fh.close()
+
+        return repr("%d:%s" % (pid, cmdline))
+    except IOError, OSError :
+        return "[%d]" % pid
 
 class WtmpEntry (object) :
     _ATTRS = (
-        "type", "pid", "line", "id", "user", "host", "exit", "session", "tv", "addr_v6"
+        "type", "pid", "line", "id", "user", "host", "exit", "session", "tv", "addr"
     )
 
     @staticmethod
@@ -19,12 +33,22 @@
         wtmp = WtmpEntry()
 
         for name, field in zip(wtmp._ATTRS, result) :
-            if isinstance(field, str) and name not in ("addr_v6", ) :
+            if isinstance(field, str) and name not in ("addr", ) :
                 field = field.rstrip("\0")
 
             setattr(wtmp, name, field)
         
-        wtmp.addr_v6 = socket.inet_ntop(socket.AF_INET6, wtmp.addr_v6)
+        # convert the address
+        family = socket.AF_INET
+        addr = wtmp.addr[0:4]
+        for byte in wtmp.addr[4:] :
+            if byte :
+                family = socket.AF_INET6
+                addr = wtmp.addr
+                break
+        
+        wtmp.addr = socket.inet_ntop(family, addr)
+        wtmp.pid = getPidCmd(wtmp.pid)
 
         return wtmp
 
@@ -66,6 +90,36 @@
     for item in read_entries(fh) :
         print item
 
+class WtmpModule (api.Module) :
+    name = "wtmp"
+    version = 0x0001
+    
+    event_types = [
+        "wtmp",
+    ]
+
+    def handleConnect (self) :
+        log.msg("Following default wtmp file...")
+
+        self.wtmp = WtmpFile()
+
+        log.msg("Starting poll timer")
+
+        self.poll()
+
+        log.msg("Running")
+
+    def poll (self) :
+
+        while True :
+            item = self.wtmp.tryRead()
+
+            if item :
+                log.msg(" -- %s" % item)
+                self.sendEvent("wtmp", str(item))
+            else :
+                return reactor.callLater(POLL_INTERVAL, self.poll)
+
 if __name__ == '__main__' :
-    follow_main()
+    WtmpModule().run()