#!/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:])
