#!/usr/local/bin/python
#
# Copyright (c) 2002 Neil Blakey-Milner
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#

import cStringIO
import os
import re
import sys
from cgi import escape

from twisted.internet import protocol, reactor
from twisted.python import log, logfile, usage
from twisted.web import server, widgets


class Options(usage.Options):
    optFlags = [
        ["profile", "p"],
        ["nodaemon", "F"],
    ]
    optParameters = [
        ["user", "u", "mailnull"],
        ["logfile", "l", None],
    ]


# (nbm@pike) /home/nbm# su mailnull -c mailq
# 44h  1.4K 18WFqX-0004ZB-00 <>
#           nagios@pike.moria.org
# 
# 44h  1.4K 18WFvX-0004d3-00 <>
#           nagios@pike.moria.org
# 
# 44h  1.4K 18WFvX-0004dC-00 <>
#           nagios@pike.moria.org
# 
# 26h  1.4K 18WWNh-00005e-00 <>
#           nagios@pike.moria.org
# 
# 26h  1.4K 18WWQ2-00007y-00 <>
#           nagios@pike.moria.org
# 
# 16h  1.4K 18WfwM-0000FI-00 <>
#           nagios@pike.moria.org
# 
# 16h  1.4K 18WfwN-0000FM-00 <>
#           nagios@pike.moria.org
# 
# 16h  1.4K 18WfwN-0000FS-00 <>
#           nagios@pike.moria.org
# 
# 16h  1.4K 18WfwN-0000FZ-00 <>
#           nagios@pike.moria.org
# 
#  2h  1.4K 18Wslh-000054-00 <>
#           nagios@pike.moria.org
# 

class Accumulator(protocol.ProcessProtocol):
    """Accumulate data from a process."""

    closed = 0

    def connectionMade(self):
        # print "connection made"
        self.outF = cStringIO.StringIO()
        self.errF = cStringIO.StringIO()

    def outReceived(self, d):
        # print "data", repr(d)
        self.outF.write(d)

    def errReceived(self, d):
        # print "err", repr(d)
        self.errF.write(d)

    def outConnectionLost(self):
        # print "out closed"
        pass

    def errConnectionLost(self):
        # print "err closed"
        pass

    def processEnded(self, reason):
        self.closed = 1
        self.status = reason


class QueueDisplay(widgets.Presentation):
    template = """<H1>Mail Queue.</h1>
    %%%%showQueue()%%%%"""

    def showQueue(self):
        r = []
        p = Accumulator()
        reactor.spawnProcess(p, "mailq", ["mailq"])
        while not p.closed:
            reactor.iterate()
        if not str(p.status.type) == "twisted.internet.error.ProcessDone":
            return p.errF.getvalue()

        t = 0
        for line in p.outF.getvalue().split('\n'):
            done = 0
            if t == 0:
                m = re.match("^(?:\s+)?(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$", line)
                if m:
                    time = m.groups()[0]
                    size = m.groups()[1]
                    identifier = m.groups()[2]
                    sender = m.groups()[3]
                    r.append("Time: %s<br>Size: %s<br>Identifier: %s<br>Sender: %s<br>" % m.groups())
                else:
                    r.append("<strong>%s</strong><br>" % line)
                t = 1
                done = 1

            if t == 1 and not done:
                m = re.match("^\s+(\S+)$", line)
                if m:
                    address = m.groups()[0]
                    r.append("Deliver address: %s<br>" % m.groups())
                else:
                    m = re.match("^$", line)
                    if m:
                        t = 0
                    else:
                        r.append("<strong>%s</strong><br>" % line)
                
            
        #r.append(p.outF.getvalue())
        return "".join(r)

def main(config):
    logPath = os.path.abspath(config['logfile'] or 'teqm.log')
    logFile = logfile.LogFile(os.path.basename(logPath), os.path.dirname(logPath))

    if not config['nodaemon']:
        # Turn into a daemon.
        if os.fork():   # launch child and...
            os._exit(0) # kill off parent
        os.setsid()
        os.umask(077)
        for i in range(3):
            try:
                os.close(i)
            except OSError, e:
                import errno
                if e.errno != errno.EBADF:
                    raise
    else:
        logFile = sys.stdout

    log.startLogging(logFile)
    gdgt = widgets.Gadget()
    gdgt.putWidget('', QueueDisplay())
    reactor.listenTCP(9080, server.Site(gdgt))
    reactor.run()

if __name__ == "__main__":
    config = Options()
    try:
        config.parseOptions()
    except usage.UsageError, errortext:
        print '%s: %s' % (sys.argv[0], errortext)
        print '%s: Try --help for usage details.' % (sys.argv[0])
        sys.exit(1)

    main(config)

