#!/usr/bin/python

import sys
from ldaptor.protocols.ldap import ldapclient, ldapsyntax
from ldaptor.protocols import pureber, pureldap
from ldaptor import ldapfilter
from twisted.internet.defer import Deferred, DeferredList
from twisted.internet import protocol, reactor

class Search(ldapclient.LDAPClient):
    def connectionMade(self):
        d=self.bind()
        d.addCallback(self._handle_bind_success)

    def _printResults(self, result, host):
        for context in result['namingContexts']:
            print '%s\t%s' % (host, context)

    def _handle_bind_success(self, x):
        matchedDN, serverSaslCreds = x
        o=ldapsyntax.LDAPEntry(client=self,
                               dn='')
        d=o.search(filterText='(objectClass=*)',
                   scope=pureldap.LDAP_SCOPE_baseObject,
                   attributes=['namingContexts'],
                   callback=(lambda x:
                             self._printResults(x, self.factory.server)))
        d.chainDeferred(self.factory.deferred)

class SearchFactory(protocol.ClientFactory):
    protocol = Search

    def __init__(self, server, deferred):
        self.server=server
        self.deferred=deferred

    def clientConnectionFailed(self, connector, reason):
        self.deferred.errback(None)

exitStatus = 0

def errback(data):
    print "ERROR:", data.getErrorMessage()
    global exitStatus
    exitStatus=1

def main(servers):
    l = []
    for server in servers:
        d=Deferred()
        l.append(d)
        s=SearchFactory(server, d)
        reactor.connectTCP(server, 389, s)
        d.addErrback(errback)
    dl = DeferredList(l)
    dl.addBoth(lambda x: reactor.stop())
    reactor.run()
    sys.exit(exitStatus)

if __name__ == "__main__":
    if not sys.argv[1:]:
        print >>sys.stderr, '%s: usage:' % sys.argv[0]
        print >>sys.stderr, '  %s HOST..' % sys.argv[0]
    else:
        main(sys.argv[1:])
