utmp.py
author Tero Marttila <terom@paivola.fi>
Wed, 26 Mar 2008 02:30:34 +0200
changeset 17 24dc72473ff9
parent 11 2d33d62cd8f8
permissions -rw-r--r--
add support for fifos in logwatch

committer: Tero Marttila <terom@paivola.fi>
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     1
from twisted.internet import protocol, reactor
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     2
from twisted.python import log
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
     3
import socket, os, time
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     5
import _utmp, api, sys
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     6
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     7
POLL_INTERVAL = 5
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     8
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
     9
def getPidCmd (pid) :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    10
    try :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    11
        fh = open("/proc/%d/cmdline" % pid, "r")
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    12
        cmdline = fh.read()
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    13
        fh.close()
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    14
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    15
        return repr("%d:%s" % (pid, cmdline))
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    16
    except IOError, OSError :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    17
        return "[%d]" % pid
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    18
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    19
class WtmpEntry (object) :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
    _ATTRS = (
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    21
        "type", "pid", "line", "id", "user", "host", "exit", "session", "tv", "addr"
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
    )
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    24
    @staticmethod
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    25
    def fromFile (file) :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    26
        bytes = file.read(_utmp.size())
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    27
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    28
        if not bytes :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    29
            return
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    30
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    31
        result = _utmp.parse(bytes)
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    32
        
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    33
        wtmp = WtmpEntry()
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    34
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    35
        for name, field in zip(wtmp._ATTRS, result) :
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    36
            if isinstance(field, str) and name not in ("addr", ) :
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    37
                field = field.rstrip("\0")
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    38
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    39
            setattr(wtmp, name, field)
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    40
        
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    41
        # convert the address
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    42
        family = socket.AF_INET
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    43
        addr = wtmp.addr[0:4]
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    44
        for byte in wtmp.addr[4:] :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    45
            if byte :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    46
                family = socket.AF_INET6
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    47
                addr = wtmp.addr
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    48
                break
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    49
        
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    50
        wtmp.addr = socket.inet_ntop(family, addr)
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    51
        wtmp.pid = getPidCmd(wtmp.pid)
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    52
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    53
        return wtmp
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    54
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
    def __str__ (self) :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
        return " ".join("%s=%s" % (key, getattr(self, key)) for key in self._ATTRS)
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    58
class WtmpFile (object) :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    59
    def __init__ (self, path="/var/log/wtmp") :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    60
        self.path = path
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    61
        self.file = open(path)
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    62
        self.file.seek(0, os.SEEK_END)
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    63
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    64
    def tryRead (self) :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    65
        return WtmpEntry.fromFile(self.file)
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    66
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    67
def read_entries (file) :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
    while True :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
        wtmp = read_entry(file)
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
        if wtmp :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
            yield wtmp
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
        else :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
            return
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
8
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    76
def follow_main () :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    77
    wtmp = WtmpFile()
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    78
    
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    79
    while True :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    80
        item = wtmp.tryRead()
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    81
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    82
        if item :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    83
            print item
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    84
        else :
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    85
            time.sleep(2)
3d648daf9538 WtmpFile && follow_main
Tero Marttila <terom@paivola.fi>
parents: 7
diff changeset
    86
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    87
def test_main () :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    88
    fh = open("/var/log/wtmp", "r")
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    89
    
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    90
    for item in read_entries(fh) :
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    91
        print item
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    92
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    93
class WtmpModule (api.Module) :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    94
    name = "wtmp"
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    95
    version = 0x0001
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    96
    
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    97
    event_types = [
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    98
        "wtmp",
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
    99
    ]
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   100
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   101
    def handleConnect (self) :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   102
        log.msg("Following default wtmp file...")
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   103
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   104
        self.wtmp = WtmpFile()
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   105
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   106
        log.msg("Starting poll timer")
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   107
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   108
        self.poll()
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   109
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   110
        log.msg("Running")
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   111
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   112
    def poll (self) :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   113
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   114
        while True :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   115
            item = self.wtmp.tryRead()
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   116
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   117
            if item :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   118
                log.msg(" -- %s" % item)
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   119
                self.sendEvent("wtmp", str(item))
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   120
            else :
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   121
                return reactor.callLater(POLL_INTERVAL, self.poll)
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   122
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   123
if __name__ == '__main__' :
11
2d33d62cd8f8 fix utmp.py, it's a proper module, doesn't tightloop and OOM, etc
Tero Marttila <terom@paivola.fi>
parents: 8
diff changeset
   124
    WtmpModule().run()
7
6a49fc285842 C module to handle utmp entires
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   125