From 5b8302f6559ffed6d45852f52cc82366fc325f0d Mon Sep 17 00:00:00 2001
From: Hallvard Furuseth <hallvard@openldap.org>
Date: Thu, 12 Dec 2002 16:32:26 +0000
Subject: [PATCH] Factor out common client code to file common.c

---
 clients/tools/Makefile.in   |  32 +-
 clients/tools/common.c      | 689 +++++++++++++++++++++++++++++
 clients/tools/common.h      |  57 +++
 clients/tools/ldapcompare.c | 716 ++----------------------------
 clients/tools/ldapdelete.c  | 727 +++----------------------------
 clients/tools/ldapmodify.c  | 739 +++----------------------------
 clients/tools/ldapmodrdn.c  | 723 ++-----------------------------
 clients/tools/ldappasswd.c  | 751 +++-----------------------------
 clients/tools/ldapsearch.c  | 841 +++++-------------------------------
 clients/tools/ldapwhoami.c  | 690 ++---------------------------
 10 files changed, 1171 insertions(+), 4794 deletions(-)
 create mode 100644 clients/tools/common.c
 create mode 100644 clients/tools/common.h

diff --git a/clients/tools/Makefile.in b/clients/tools/Makefile.in
index cda849bacb..0d742ed3fe 100644
--- a/clients/tools/Makefile.in
+++ b/clients/tools/Makefile.in
@@ -3,9 +3,9 @@
 ## Makefile for LDAP tools
 ##
 SRCS	= ldapsearch.c ldapmodify.c ldapdelete.c ldapmodrdn.c \
-		ldappasswd.c ldapwhoami.c ldapcompare.c
+		ldappasswd.c ldapwhoami.c ldapcompare.c common.c
 OBJS	= ldapsearch.o ldapmodify.o ldapdelete.o ldapmodrdn.o \
-		ldappasswd.o ldapwhoami.o ldapcompare.o
+		ldappasswd.o ldapwhoami.o ldapcompare.o common.o
 
 LDAP_INCDIR= ../../include       
 LDAP_LIBDIR= ../../libraries
@@ -21,56 +21,56 @@ PROGRAMS = ldapsearch ldapmodify ldapdelete ldapmodrdn ldapadd \
 
 
 ldapsearch:	ldsversion.o
-	$(LTLINK) -o $@ ldapsearch.o ldsversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapsearch.o common.o ldsversion.o $(LIBS)
 
 ldapmodify:	ldmversion.o
-	$(LTLINK) -o $@ ldapmodify.o ldmversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapmodify.o common.o ldmversion.o $(LIBS)
 
 ldapdelete:	lddversion.o
-	$(LTLINK) -o $@ ldapdelete.o lddversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapdelete.o common.o lddversion.o $(LIBS)
 
 ldapmodrdn:	ldrversion.o
-	$(LTLINK) -o $@ ldapmodrdn.o ldrversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapmodrdn.o common.o ldrversion.o $(LIBS)
 
 ldappasswd:	ldpversion.o
-	$(LTLINK) -o $@ ldappasswd.o ldpversion.o $(LIBS)
+	$(LTLINK) -o $@ ldappasswd.o common.o ldpversion.o $(LIBS)
 
 ldapwhoami:	ldwversion.o
-	$(LTLINK) -o $@ ldapwhoami.o ldwversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapwhoami.o common.o ldwversion.o $(LIBS)
 
 ldapcompare: ldcversion.o
-	$(LTLINK) -o $@ ldapcompare.o ldcversion.o $(LIBS)
+	$(LTLINK) -o $@ ldapcompare.o common.o ldcversion.o $(LIBS)
 
 ldapadd:	ldapmodify
 	@-$(RM) $@$(EXEEXT)
 	$(LN_H) ldapmodify$(EXEEXT) ldapadd$(EXEEXT)
 
 
-ldsversion.c: ldapsearch.o $(XLIBS)
+ldsversion.c: ldapsearch.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapsearch > $@
 
-ldmversion.c: ldapmodify.o $(XLIBS)
+ldmversion.c: ldapmodify.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapmodify > $@
 
-lddversion.c: ldapdelete.o $(XLIBS)
+lddversion.c: ldapdelete.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapdelete > $@
 
-ldpversion.c: ldappasswd.o $(XLIBS)
+ldpversion.c: ldappasswd.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldappasswd > $@
 
-ldrversion.c: ldapmodrdn.o $(XLIBS)
+ldrversion.c: ldapmodrdn.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapmodrdn > $@
 
-ldwversion.c: ldapwhoami.o $(XLIBS)
+ldwversion.c: ldapwhoami.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapwhoami > $@
 
-ldcversion.c: ldapcompare.o $(XLIBS)
+ldcversion.c: ldapcompare.o common.o $(XLIBS)
 	@-$(RM) $@
 	$(MKVERSION) ldapcompare > $@
 
diff --git a/clients/tools/common.c b/clients/tools/common.c
new file mode 100644
index 0000000000..afcc937411
--- /dev/null
+++ b/clients/tools/common.c
@@ -0,0 +1,689 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* common.c - common routines for the ldap client tools */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdlib.h>
+#include <ac/signal.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/errno.h>
+
+#include <ldap.h>
+
+#include "lutil_ldap.h"
+
+#include "common.h"
+
+
+int   authmethod = -1;
+char *binddn = NULL;
+int   contoper = 0;
+int   debug = 0;
+char *infile = NULL;
+char *ldapuri = NULL;
+char *ldaphost = NULL;
+int   ldapport = 0;
+#ifdef HAVE_CYRUS_SASL
+unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
+char	*sasl_realm = NULL;
+char	*sasl_authc_id = NULL;
+char	*sasl_authz_id = NULL;
+char	*sasl_mech = NULL;
+char	*sasl_secprops = NULL;
+#endif
+int   use_tls = 0;
+
+char *authzid = NULL;
+int   manageDSAit = 0;
+int   noop = 0;
+
+int   not = 0;
+int   want_bindpw = 0;
+struct berval passwd = { 0, NULL };
+char *pw_file = NULL;
+int   referrals = 0;
+int   verbose = 0;
+int   version = -1;
+
+
+/* Set in main() */
+char *prog;
+
+
+void
+tool_common_usage( void )
+{
+	static const char *const descriptions[] = {
+"  -c         continuous operation mode (do not stop on errors)\n",
+"  -C         chase referrals\n",
+"  -d level   set LDAP debugging level to `level'\n",
+"  -D binddn  bind DN\n",
+"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
+"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
+"             [!]manageDSAit       (alternate form, see -M)\n"
+"             [!]noop\n",
+"  -f file    read operations from `file'\n",
+"  -h host    LDAP server\n",
+"  -H URI     LDAP Uniform Resource Indentifier(s)\n",
+"  -I         use SASL Interactive mode\n",
+"  -k         use Kerberos authentication\n",
+"  -K         like -k, but do only step 1 of the Kerberos bind\n",
+"  -M         enable Manage DSA IT control (-MM to make critical)\n",
+"  -n         show what would be done but don't actually do it\n",
+"  -O props   SASL security properties\n",
+"  -p port    port on LDAP server\n",
+"  -P version procotol version (default: 3)\n",
+"  -Q         use SASL Quiet mode\n",
+"  -R realm   SASL realm\n",
+"  -U authcid SASL authentication identity\n",
+"  -v         run in verbose mode (diagnostics to standard output)\n",
+"  -w passwd  bind passwd (for simple authentication)\n",
+"  -W         prompt for bind passwd\n",
+"  -x         Simple authentication\n",
+"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n",
+"  -y file    Read passwd from file\n",
+"  -Y mech    SASL mechanism\n",
+"  -Z         Start TLS request (-ZZ to require successful response)\n",
+NULL
+	};
+	const char *const *cpp, *cp;
+
+	fputs( "Common options:\n", stderr );
+	for( cpp = descriptions; (cp = *cpp) != NULL; cpp++ )
+		if( strchr( options, cp[3] ) )
+			fputs( cp, stderr );
+}
+
+
+void
+tool_args( int argc, char **argv )
+{
+	int i;
+    while (( i = getopt( argc, argv, options )) != EOF )
+	{
+		int crit;
+		char *control, *cvalue;
+		switch( i ) {
+		case 'c':	/* continuous operation mode */
+			contoper = 1;
+			break;
+		case 'C':
+			referrals = 1;
+			break;
+		case 'd':
+			debug |= atoi( optarg );
+			break;
+		case 'D':	/* bind DN */
+			if( binddn != NULL ) {
+				fprintf( stderr, "%s: -D previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			binddn = ber_strdup( optarg );
+			break;
+		case 'e': /* general controls */
+			/* should be extended to support comma separated list of
+			 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
+			 */
+
+			crit = 0;
+			cvalue = NULL;
+			if( optarg[0] == '!' ) {
+				crit = 1;
+				optarg++;
+			}
+
+			control = ber_strdup( optarg );
+			if ( (cvalue = strchr( control, '=' )) != NULL ) {
+				*cvalue++ = '\0';
+			}
+
+			if ( strcasecmp( control, "authzid" ) == 0 ) {
+				if( authzid != NULL ) {
+					fprintf( stderr, "authzid control previously specified\n");
+					exit( EXIT_FAILURE );
+				}
+				if( cvalue == NULL ) {
+					fprintf( stderr, "authzid: control value expected\n" );
+					usage();
+				}
+				if( !crit ) {
+					fprintf( stderr, "authzid: must be marked critical\n" );
+					usage();
+				}
+
+				assert( authzid == NULL );
+				authzid = cvalue;
+
+			} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
+				if( manageDSAit ) {
+					fprintf( stderr,
+					         "manageDSAit control previously specified\n");
+					exit( EXIT_FAILURE );
+				}
+				if( cvalue != NULL ) {
+					fprintf( stderr,
+					         "manageDSAit: no control value expected\n" );
+					usage();
+				}
+
+				manageDSAit = 1 + crit;
+
+			} else if ( strcasecmp( control, "noop" ) == 0 ) {
+				if( noop ) {
+					fprintf( stderr, "noop control previously specified\n");
+					exit( EXIT_FAILURE );
+				}
+				if( cvalue != NULL ) {
+					fprintf( stderr, "noop: no control value expected\n" );
+					usage();
+				}
+
+				noop = 1 + crit;
+
+			} else {
+				fprintf( stderr, "Invalid general control name: %s\n",
+				         control );
+				usage();
+			}
+			break;
+		case 'f':	/* read from file */
+			if( infile != NULL ) {
+				fprintf( stderr, "%s: -f previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			infile = ber_strdup( optarg );
+			break;
+		case 'h':	/* ldap host */
+			if( ldaphost != NULL ) {
+				fprintf( stderr, "%s: -h previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			ldaphost = ber_strdup( optarg );
+			break;
+		case 'H':	/* ldap URI */
+			if( ldapuri != NULL ) {
+				fprintf( stderr, "%s: -H previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			ldapuri = ber_strdup( optarg );
+			break;
+		case 'I':
+#ifdef HAVE_CYRUS_SASL
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible previous "
+						 "authentication choice\n",
+						 prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_flags = LDAP_SASL_INTERACTIVE;
+			break;
+#else
+			fprintf( stderr, "%s: was not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+		case 'k':	/* kerberos bind */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+			if( authmethod != -1 ) {
+				fprintf( stderr, "%s: -k incompatible with previous "
+						 "authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_KRBV4;
+#else
+			fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'K':	/* kerberos bind, part one only */
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+			if( authmethod != -1 ) {
+				fprintf( stderr, "%s: incompatible with previous "
+						 "authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_KRBV41;
+#else
+			fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'M':
+			/* enable Manage DSA IT */
+			manageDSAit = 1;
+			break;
+		case 'n':	/* print operations, don't actually do them */
+			not = 1;
+			break;
+		case 'O':
+#ifdef HAVE_CYRUS_SASL
+			if( sasl_secprops != NULL ) {
+				fprintf( stderr, "%s: -O previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible previous "
+						 "authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_secprops = ber_strdup( optarg );
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'p':
+			if( ldapport ) {
+				fprintf( stderr, "%s: -p previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			ldapport = atoi( optarg );
+			break;
+		case 'P':
+			switch( atoi(optarg) ) {
+			case 2:
+				if( version == LDAP_VERSION3 ) {
+					fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+							 prog, version );
+					exit( EXIT_FAILURE );
+				}
+				version = LDAP_VERSION2;
+				break;
+			case 3:
+				if( version == LDAP_VERSION2 ) {
+					fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
+							 prog, version );
+					exit( EXIT_FAILURE );
+				}
+				version = LDAP_VERSION3;
+				break;
+			default:
+				fprintf( stderr, "%s: protocol version should be 2 or 3\n",
+						 prog );
+				usage();
+			}
+			break;
+		case 'Q':
+#ifdef HAVE_CYRUS_SASL
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible previous "
+						 "authentication choice\n",
+						 prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_flags = LDAP_SASL_QUIET;
+			break;
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+		case 'R':
+#ifdef HAVE_CYRUS_SASL
+			if( sasl_realm != NULL ) {
+				fprintf( stderr, "%s: -R previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible previous "
+						 "authentication choice\n",
+						 prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_realm = ber_strdup( optarg );
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'U':
+#ifdef HAVE_CYRUS_SASL
+			if( sasl_authc_id != NULL ) {
+				fprintf( stderr, "%s: -U previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible previous "
+						 "authentication choice\n",
+						 prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_authc_id = ber_strdup( optarg );
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'v':	/* verbose mode */
+			verbose = 1;
+			break;
+		case 'w':	/* password */
+			passwd.bv_val = ber_strdup( optarg );
+			{
+				char* p;
+
+				for( p = optarg; *p != '\0'; p++ ) {
+					*p = '\0';
+				}
+			}
+			passwd.bv_len = strlen( passwd.bv_val );
+			break;
+		case 'W':
+			want_bindpw = 1;
+			break;
+		case 'y':
+			pw_file = optarg;
+			break;
+		case 'Y':
+#ifdef HAVE_CYRUS_SASL
+			if( sasl_mech != NULL ) {
+				fprintf( stderr, "%s: -Y previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_mech = ber_strdup( optarg );
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n",
+					 prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'x':
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
+				fprintf( stderr, "%s: incompatible with previous "
+						 "authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SIMPLE;
+			break;
+		case 'X':
+#ifdef HAVE_CYRUS_SASL
+			if( sasl_authz_id != NULL ) {
+				fprintf( stderr, "%s: -X previously specified\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
+				fprintf( stderr, "%s: -X incompatible with "
+						 "authentication choice\n", prog );
+				exit( EXIT_FAILURE );
+			}
+			authmethod = LDAP_AUTH_SASL;
+			sasl_authz_id = ber_strdup( optarg );
+#else
+			fprintf( stderr, "%s: not compiled with SASL support\n", prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		case 'Z':
+#ifdef HAVE_TLS
+			use_tls = 1;
+#else
+			fprintf( stderr, "%s: not compiled with TLS support\n", prog );
+			exit( EXIT_FAILURE );
+#endif
+			break;
+		default:
+			if( handle_private_option( i ) )
+				break;
+			fprintf( stderr, "%s: unrecognized option -%c\n",
+					 prog, optopt );
+			usage();
+		}
+    }
+
+	if (version == -1)
+		version = LDAP_VERSION3;
+
+	if (authmethod == -1 && version > LDAP_VERSION2) {
+#ifdef HAVE_CYRUS_SASL
+		authmethod = LDAP_AUTH_SASL;
+#else
+		authmethod = LDAP_AUTH_SIMPLE;
+#endif
+	}
+
+	if( ldapuri != NULL ) {
+		if( ldaphost != NULL ) {
+			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
+			exit( EXIT_FAILURE );
+		}
+		if( ldapport ) {
+			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
+			exit( EXIT_FAILURE );
+		}
+	}
+	if( version == LDAP_VERSION2 ) {
+		if( authzid || manageDSAit || noop ) {
+			fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog );
+			exit( EXIT_FAILURE );
+		}
+#ifdef HAVE_TLS
+		if( use_tls ) {
+			fprintf( stderr, "%s: -Z incompatible with LDAPv2\n", prog );
+			exit( EXIT_FAILURE );
+		}
+#endif
+#ifdef HAVE_CYRUS_SASL
+		if( authmethod == LDAP_AUTH_SASL ) {
+			fprintf( stderr, "%s: -[IOQRUXY] incompatible with LDAPv2\n",
+			         prog );
+			exit( EXIT_FAILURE );
+		}
+#endif
+	} else {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+		if ( authmethod = LDAP_AUTH_KRBV4 || authmethod == LDAP_AUTH_KRBV41 ) {
+			fprintf( stderr, "%s: -k/-K incompatible with LDAPv%d\n",
+			         prog, version );
+			exit( EXIT_FAILURE );
+		}
+#endif
+	}
+}
+
+
+LDAP *
+tool_conn_setup( int not, void (*private_setup)( LDAP * ) )
+{
+	LDAP *ld = NULL;
+
+	if ( debug ) {
+		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
+		    != LBER_OPT_SUCCESS ) {
+			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
+		}
+		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
+		    != LDAP_OPT_SUCCESS ) {
+			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
+		}
+	}
+
+#ifdef SIGPIPE
+	(void) SIGNAL( SIGPIPE, SIG_IGN );
+#endif
+
+	if ( !not ) {
+		/* connect to server */
+		if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
+			if ( verbose ) {
+				fprintf( stderr, "ldap_init( %s, %d )\n",
+				         ldaphost != NULL ? ldaphost : "<DEFAULT>",
+				         ldapport );
+			}
+
+			ld = ldap_init( ldaphost, ldapport );
+			if( ld == NULL ) {
+				char buf[20 + sizeof(": ldap_init")];
+				sprintf( buf, "%.20s: ldap_init", prog );
+				perror( buf );
+				exit( EXIT_FAILURE );
+			}
+
+		} else {
+			int rc;
+			if ( verbose ) {
+				fprintf( stderr, "ldap_initialize( %s )\n",
+				         ldapuri != NULL ? ldapuri : "<DEFAULT>" );
+			}
+			rc = ldap_initialize( &ld, ldapuri );
+			if( rc != LDAP_SUCCESS ) {
+				fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
+				         rc, ldap_err2string(rc) );
+				exit( EXIT_FAILURE );
+			}
+		}
+
+		if( private_setup )
+			private_setup( ld );
+
+		/* referrals */
+		if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
+			                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF )
+			!= LDAP_OPT_SUCCESS )
+		{
+			fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
+			         referrals ? "on" : "off" );
+			exit( EXIT_FAILURE );
+		}
+
+		if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
+		    != LDAP_OPT_SUCCESS )
+		{
+			fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
+			         version );
+			exit( EXIT_FAILURE );
+		}
+
+		if ( use_tls &&
+		     ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
+			ldap_perror( ld, "ldap_start_tls" );
+			if ( use_tls > 1 ) {
+				exit( EXIT_FAILURE );
+			}
+		}
+	}
+
+	return ld;
+}
+
+
+void
+tool_bind( LDAP *ld )
+{
+	if ( authmethod == LDAP_AUTH_SASL ) {
+#ifdef HAVE_CYRUS_SASL
+		void *defaults;
+		int rc;
+
+		if( sasl_secprops != NULL ) {
+			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
+				(void *) sasl_secprops );
+
+			if( rc != LDAP_OPT_SUCCESS ) {
+				fprintf( stderr,
+					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
+					sasl_secprops );
+				exit( EXIT_FAILURE );
+			}
+		}
+
+		defaults = lutil_sasl_defaults( ld,
+			sasl_mech,
+			sasl_realm,
+			sasl_authc_id,
+			passwd.bv_val,
+			sasl_authz_id );
+
+		rc = ldap_sasl_interactive_bind_s( ld, binddn,
+			sasl_mech, NULL, NULL,
+			sasl_flags, lutil_sasl_interact, defaults );
+
+		if( rc != LDAP_SUCCESS ) {
+			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
+			exit( EXIT_FAILURE );
+		}
+#else
+		fprintf( stderr, "%s: not compiled with SASL support\n",
+			prog );
+		exit( EXIT_FAILURE );
+#endif
+	} else {
+		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
+		     != LDAP_SUCCESS ) {
+			ldap_perror( ld, "ldap_bind" );
+			exit( EXIT_FAILURE );
+		}
+	}
+}
+
+
+/* Set server controls.  Add controls extra_c[0..count-1], if set. */
+void
+tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
+{
+	int i = 0, j, crit, err;
+	LDAPControl c[3], *ctrls[10];
+
+	if ( authzid ) {
+		c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
+		c[i].ldctl_value.bv_val = authzid;
+		c[i].ldctl_value.bv_len = strlen( authzid );
+		c[i].ldctl_iscritical = 1;
+		ctrls[i] = &c[i];
+		i++;
+	}
+
+	if ( manageDSAit ) {
+		c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+		c[i].ldctl_value.bv_val = NULL;
+		c[i].ldctl_value.bv_len = 0;
+		c[i].ldctl_iscritical = manageDSAit > 1;
+		ctrls[i] = &c[i];
+		i++;
+	}
+
+	if ( noop ) {
+		c[i].ldctl_oid = LDAP_CONTROL_NOOP;
+		c[i].ldctl_value.bv_val = NULL;
+		c[i].ldctl_value.bv_len = 0;
+		c[i].ldctl_iscritical = noop > 1;
+		ctrls[i] = &c[i];
+		i++;
+	}
+	
+	while ( count-- )
+		ctrls[i++] = extra_c++;
+	ctrls[i] = NULL;
+
+	err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
+
+	if( err != LDAP_OPT_SUCCESS ) {
+		for ( j = crit = 0; j < i; j++ )
+			if ( ctrls[j]->ldctl_iscritical )
+				crit = 1;
+		fprintf( stderr, "Could not set %scontrols\n",
+				 crit ? "critical " : "" );
+		if ( crit ) {
+			exit( EXIT_FAILURE );
+		}
+	}
+}
diff --git a/clients/tools/common.h b/clients/tools/common.h
new file mode 100644
index 0000000000..6b2710501d
--- /dev/null
+++ b/clients/tools/common.h
@@ -0,0 +1,57 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* common.h - common definitions for the ldap client tools */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+/* Defined and set in common.c */
+extern int   authmethod;
+extern char *binddn;
+extern int   contoper;
+extern int   debug;
+extern char *infile;
+extern char *ldapuri;
+extern char *ldaphost;
+extern int   ldapport;
+#ifdef HAVE_CYRUS_SASL
+extern unsigned sasl_flags;
+extern char	*sasl_realm;
+extern char	*sasl_authc_id;
+extern char	*sasl_authz_id;
+extern char	*sasl_mech;
+extern char	*sasl_secprops;
+#endif
+extern int   use_tls;
+
+extern char *authzid;
+extern int   manageDSAit;
+extern int   noop;
+
+extern int   not;
+extern int   want_bindpw;
+extern struct berval passwd;
+extern char *pw_file;
+extern int   referrals;
+extern int   verbose;
+extern int   version;
+
+/* Defined in common.c, set in main() */
+char *prog;
+
+/* Defined in main program */
+extern const char options[];
+void usage LDAP_P(( void )) LDAP_GCCATTR((noreturn));
+int handle_private_option LDAP_P(( int i ));
+
+/* Defined in common.c */
+void tool_common_usage LDAP_P(( void ));
+void tool_args LDAP_P(( int, char ** ));
+LDAP *tool_conn_setup LDAP_P(( int dont, void (*private_setup)( LDAP * ) ));
+void tool_bind LDAP_P(( LDAP * ));
+void tool_server_controls LDAP_P(( LDAP *, LDAPControl *, int ));
+
+#endif /* _COMMON_H_ */
diff --git a/clients/tools/ldapcompare.c b/clients/tools/ldapcompare.c
index 17040324dc..ef019e90dc 100644
--- a/clients/tools/ldapcompare.c
+++ b/clients/tools/ldapcompare.c
@@ -11,7 +11,6 @@
 #include <ac/stdlib.h>
 
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 #include <ac/errno.h>
@@ -34,8 +33,14 @@
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
-static void
-usage( const char *s )
+#include "common.h"
+
+
+static int quiet = 0;
+
+
+void
+usage( void )
 {
 	fprintf( stderr,
 "usage: %s [options] DN <attr:value|attr::b64value>\n"
@@ -45,37 +50,10 @@ usage( const char *s )
 "  value\tassertion value\n"
 "  b64value\tbase64 encoding of assertion value\n"
 
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -h host    LDAP server\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -k         use Kerberos authentication\n"
-"  -K         like -k, but do only step 1 of the Kerberos bind\n"
-"  -M         enable Manage DSA IT control (-MM to make critical)\n"
-"  -n         show what would be done but don't actually compare\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -P version procotol version (default: 3)\n"
+"Compare options:\n"
 "  -z         Quiet mode, don't print anything, use return values\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-, s );
-
+	         , prog );
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
@@ -88,56 +66,21 @@ static int docompare LDAP_P((
 	LDAPControl **sctrls,
 	LDAPControl **cctrls));
 
-static char *prog = NULL;
-static char	*binddn = NULL;
-static struct berval passwd = { 0, NULL };
-static char	*ldaphost = NULL;
-static char *ldapuri = NULL;
-static int	ldapport = 0;
-#ifdef HAVE_CYRUS_SASL
-static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
-static char	*sasl_realm = NULL;
-static char	*sasl_authc_id = NULL;
-static char	*sasl_authz_id = NULL;
-static char	*sasl_mech = NULL;
-static char	*sasl_secprops = NULL;
-#endif
-static int	use_tls = 0;
-static int	verbose, not;
+
+const char options[] = "z" "Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
 
 int
-main( int argc, char **argv )
+handle_private_option( int i )
 {
-	char	*compdn = NULL, *attrs = NULL;
-	char	*sep;
-	int		rc, i, crit, manageDSAit, noop, quiet;
-	int		referrals, debug;
-	int		authmethod, version, want_bindpw;
-	LDAP	*ld = NULL;
-	struct berval bvalue = { 0, NULL };
-	char	*pw_file = NULL;
-	char	*control, *cvalue;
-	char	*authzid = NULL;
-
-	debug = verbose = not = referrals = noop =
-		manageDSAit = want_bindpw = quiet = 0;
-
-	version = -1;
-
-	authmethod = -1;
-
-	prog = lutil_progname( "ldapcompare", argc, argv );
-
-	while (( i = getopt( argc, argv,
-		"Cd:D:e:h:H:IkKMnO:p:P:qQR:U:vw:WxX:y:Y:zZ")) != EOF )
-	{
-		switch( i ) {
+	switch ( i ) {
 #if 0
+		char	*control, *cvalue;
+		int		crit;
 	case 'E': /* compare controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -156,446 +99,35 @@ main( int argc, char **argv )
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid compare control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
+		usage();
 #endif
 
-		/* Common Options */
-		case 'C':
-			referrals++;
-			break;
-		case 'd':
-			debug |= atoi( optarg );
-			break;
-		case 'D':	/* bind DN */
-			if( binddn != NULL ) {
-				fprintf( stderr, "%s: -D previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			binddn = strdup( optarg );
-			break;
-
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
+	case 'z':
+		quiet = 1;
+		break;
 
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
+	default:
+		return 0;
+	}
+	return 1;
+}
 
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
-
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			noop = 1 + crit;
 
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
+int
+main( int argc, char **argv )
+{
+	char	*compdn = NULL, *attrs = NULL;
+	char	*sep;
+	int		rc;
+	LDAP	*ld = NULL;
+	struct berval bvalue = { 0, NULL };
 
-		case 'h':	/* ldap host */
-			if( ldapuri != NULL ) {
-				fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( ldaphost != NULL ) {
-				fprintf( stderr, "%s: -h previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			ldaphost = strdup( optarg );
-			break;
-		case 'H':	/* ldap URI */
-			if( ldaphost != NULL ) {
-				fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( ldapport ) {
-				fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( ldapuri != NULL ) {
-				fprintf( stderr, "%s: -H previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			ldapuri = strdup( optarg );
-			break;
-		case 'I':
-#ifdef HAVE_CYRUS_SASL
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -I incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible previous "
-					"authentication choice\n",
-					prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_flags = LDAP_SASL_INTERACTIVE;
-			break;
-#else
-			fprintf( stderr, "%s: was not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-		case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-			if( version > LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-
-			if( authmethod != -1 ) {
-				fprintf( stderr, "%s: -k incompatible with previous "
-					"authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-
-			authmethod = LDAP_AUTH_KRBV4;
-#else
-			fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-			return EXIT_FAILURE;
-#endif
-			break;
-		case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-			if( version > LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 ) {
-				fprintf( stderr, "%s: incompatible with previous "
-					"authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-
-			authmethod = LDAP_AUTH_KRBV41;
-#else
-			fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		case 'M':
-			/* enable Manage DSA IT */
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			manageDSAit++;
-			version = LDAP_VERSION3;
-			break;
-		case 'n':	/* print compares, don't actually do them */
-			++not;
-			break;
-		case 'O':
-#ifdef HAVE_CYRUS_SASL
-			if( sasl_secprops != NULL ) {
-				fprintf( stderr, "%s: -O previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible previous "
-					"authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_secprops = strdup( optarg );
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		case 'p':
-			if( ldapport ) {
-				fprintf( stderr, "%s: -p previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			ldapport = atoi( optarg );
-			break;
-		case 'P':
-			switch( atoi(optarg) ) {
-			case 2:
-				if( version == LDAP_VERSION3 ) {
-					fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-						prog, version );
-					return EXIT_FAILURE;
-				}
-				version = LDAP_VERSION2;
-				break;
-			case 3:
-				if( version == LDAP_VERSION2 ) {
-					fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-						prog, version );
-					return EXIT_FAILURE;
-				}
-				version = LDAP_VERSION3;
-				break;
-			default:
-				fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-					prog );
-				usage( prog );
-				return( EXIT_FAILURE );
-			}
-			break;
-		case 'Q':
-#ifdef HAVE_CYRUS_SASL
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -Q incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible previous "
-					"authentication choice\n",
-					prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_flags = LDAP_SASL_QUIET;
-			break;
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-		case 'R':
-#ifdef HAVE_CYRUS_SASL
-			if( sasl_realm != NULL ) {
-				fprintf( stderr, "%s: -R previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -R incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible previous "
-					"authentication choice\n",
-					prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_realm = strdup( optarg );
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-			if( sasl_authc_id != NULL ) {
-				fprintf( stderr, "%s: -U previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -U incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible previous "
-					"authentication choice\n",
-					prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_authc_id = strdup( optarg );
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		case 'v':	/* verbose mode */
-			verbose++;
-			break;
-		case 'w':	/* password */
-			passwd.bv_val = strdup( optarg );
-			{
-				char* p;
-
-				for( p = optarg; *p != '\0'; p++ ) {
-					*p = '\0';
-				}
-			}
-			passwd.bv_len = strlen( passwd.bv_val );
-			break;
-		case 'W':
-			want_bindpw++;
-			break;
-		case 'y':
-			pw_file = optarg;
-			break;
-		case 'Y':
-#ifdef HAVE_CYRUS_SASL
-			if( sasl_mech != NULL ) {
-				fprintf( stderr, "%s: -Y previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -Y incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_mech = strdup( optarg );
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		case 'x':
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-				fprintf( stderr, "%s: incompatible with previous "
-					"authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SIMPLE;
-			break;
-		case 'X':
-#ifdef HAVE_CYRUS_SASL
-			if( sasl_authz_id != NULL ) {
-				fprintf( stderr, "%s: -X previously specified\n", prog );
-				return EXIT_FAILURE;
-			}
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-				fprintf( stderr, "%s: -X incompatible with "
-					"authentication choice\n", prog );
-				return EXIT_FAILURE;
-			}
-			authmethod = LDAP_AUTH_SASL;
-			version = LDAP_VERSION3;
-			sasl_authz_id = strdup( optarg );
-#else
-			fprintf( stderr, "%s: not compiled with SASL support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		case 'z':
-			quiet++;
-			break;
-		case 'Z':
-#ifdef HAVE_TLS
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -Z incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			use_tls++;
-#else
-			fprintf( stderr, "%s: not compiled with TLS support\n",
-				prog );
-			return( EXIT_FAILURE );
-#endif
-			break;
-		default:
-			fprintf( stderr, "%s: unrecognized option -%c\n",
-				prog, optopt );
-			usage( argv[0] );
-		}
-	}
+	prog = lutil_progname( "ldapcompare", argc, argv );
 
-	if (version == -1) {
-		version = LDAP_VERSION3;
-	}
-	if (authmethod == -1 && version > LDAP_VERSION2) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+	tool_args( argc, argv );
 
 	if ( argc - optind != 2 ) {
-		usage( argv[ 0 ] );
+		usage();
 	}
 
 	compdn = argv[optind++];
@@ -606,7 +138,7 @@ main( int argc, char **argv )
 	 */
 	sep = strchr(attrs, ':');
 	if (!sep) {
-		usage( argv[ 0 ] );
+		usage();
 	}
 
 	*sep++='\0';
@@ -626,82 +158,10 @@ main( int argc, char **argv )
 		}
 	}
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
-			!= LBER_OPT_SUCCESS )
-		{
-			fprintf( stderr,
-				"Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
-			!= LDAP_OPT_SUCCESS )
-		{
-			fprintf( stderr,
-				"Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
+	if ( debug )
 		ldif_debug = debug;
-	}
-
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
 
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapcompare: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr,
-				"Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-
-	/* referrals */
-	if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	if (version == -1 ) {
-		version = LDAP_VERSION3;
-	}
-
-	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
-		!= LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
-			version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return EXIT_FAILURE;
-		}
-	}
+	ld = tool_conn_setup( 0, 0 );
 
 	if ( pw_file || want_bindpw ) {
 		if ( pw_file ) {
@@ -713,98 +173,10 @@ main( int argc, char **argv )
 		}
 	}
 
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return EXIT_FAILURE;
-			}
-		}
-
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
+	tool_bind( ld );
 
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return EXIT_FAILURE;
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog, argv[0] );
-		return EXIT_FAILURE;
-#endif
-	} else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return EXIT_FAILURE;
-		}
-	}
-
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
-
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
 	if ( verbose ) {
 		fprintf( stderr, "DN:%s, attr:%s, value:%s\n",
diff --git a/clients/tools/ldapdelete.c b/clients/tools/ldapdelete.c
index b46e38791e..26424fea65 100644
--- a/clients/tools/ldapdelete.c
+++ b/clients/tools/ldapdelete.c
@@ -11,8 +11,6 @@
 
 #include <ac/stdlib.h>
 #include <ac/ctype.h>
-
-#include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 
@@ -21,24 +19,11 @@
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
-static char	*prog;
-static char	*binddn = NULL;
-static struct berval passwd = { 0, NULL };
-static char *ldapuri = NULL;
-static char	*ldaphost = NULL;
-static int	ldapport = 0;
+#include "common.h"
+
+
 static int	prune = 0;
-#ifdef HAVE_CYRUS_SASL
-static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
-static char	*sasl_mech = NULL;
-static char *sasl_realm = NULL;
-static char	*sasl_authc_id = NULL;
-static char	*sasl_authz_id = NULL;
-static char	*sasl_secprops = NULL;
-#endif
-static int	use_tls = 0;
-static int	not, verbose, contoper;
-static LDAP	*ld = NULL;
+
 
 static int dodelete LDAP_P((
     LDAP *ld,
@@ -48,8 +33,8 @@ static int deletechildren LDAP_P((
 	LDAP *ld,
 	const char *dn ));
 
-static void
-usage( const char *s )
+void
+usage( void )
 {
 	fprintf( stderr,
 "Delete entries from an LDAP server\n\n"
@@ -58,75 +43,26 @@ usage( const char *s )
 "	    or from the file specified with \"-f file\".\n"
 "Delete Options:\n"
 "  -r         delete recursively\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -k         use Kerberos authentication\n"
-"  -K         like -k, but do only step 1 of the Kerberos bind\n"
-"  -M         enable Manage DSA IT control (-MM to make critical)\n"
-"  -n         show what would be done but don't actually do it\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -P version procotol version (default: 3)\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-,		s );
-
+			 , prog );
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
 
+const char options[] = "r" "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
+
 int
-main( int argc, char **argv )
+handle_private_option( int i )
 {
-	char		buf[ 4096 ];
-	FILE		*fp;
-	int		i, rc, retval, authmethod, referrals, want_bindpw;
-	int		version, debug, manageDSAit, noop, crit;
-	char	*pw_file;
-	char	*control, *cvalue;
-	char	*authzid = NULL;
-
-    not = verbose = contoper = want_bindpw = debug
-		= manageDSAit = noop = referrals = 0;
-    fp = NULL;
-    authmethod = -1;
-	version = -1;
-	pw_file = NULL;
-
-    prog = lutil_progname( "ldapdelete", argc, argv );
-
-    while (( i = getopt( argc, argv, "cf:r"
-		"Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
-	{
-	switch( i ) {
-	/* Delete Specific Options */
-	case 'c':	/* continuous operation mode */
-	    ++contoper;
-	    break;
+	switch ( i ) {
+#if 0
+		int crit;
+		char *control, *cvalue;
 	case 'E': /* delete controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -145,527 +81,55 @@ main( int argc, char **argv )
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid delete control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
-	case 'f':	/* read DNs from a file */
-		if( fp != NULL ) {
-			fprintf( stderr, "%s: -f previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    if (( fp = fopen( optarg, "r" )) == NULL ) {
-		perror( optarg );
-		exit( EXIT_FAILURE );
-	    }
-	    break;
+		usage();
+#endif
+
 	case 'r':
 		prune = 1;
 		break;
 
-	/* Common Options */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
-
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
-
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
+	default:
+		return 0;
+	}
+	return 1;
+}
 
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
 
-			noop = 1 + crit;
+static void
+private_conn_setup( LDAP *ld )
+{
+	/* this seems prudent for searches below */
+	int deref = LDAP_DEREF_NEVER;
+	ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
+}
 
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return EXIT_FAILURE;
-#endif
-	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
+int
+main( int argc, char **argv )
+{
+	char		buf[ 4096 ];
+	FILE		*fp;
+	LDAP		*ld;
+	int		rc, retval;
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'M':
-		/* enable Manage DSA IT */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		manageDSAit++;
-		version = LDAP_VERSION3;
-		break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
-	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
-		}
-		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = strdup( optarg );
-		{
-			char* p;
+    fp = NULL;
 
-			for( p = optarg; *p != '\0'; p++ ) {
-				*p = '\0';
-			}
-		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'y':
-		pw_file = optarg;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	default:
-		fprintf( stderr, "%s: unrecognized option -%c\n",
-			prog, optopt );
-		usage( prog );
-		return( EXIT_FAILURE );
-	}
-    }
+    prog = lutil_progname( "ldapdelete", argc, argv );
 
-	if (version == -1) {
-		version = LDAP_VERSION3;
-	}
-	if (authmethod == -1 && version > LDAP_VERSION2) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+	tool_args( argc, argv );
 
-    if ( fp == NULL ) {
+	if ( infile != NULL ) {
+		if (( fp = fopen( infile, "r" )) == NULL ) {
+			perror( optarg );
+			exit( EXIT_FAILURE );
+	    }
+	} else {
 	if ( optind >= argc ) {
 	    fp = stdin;
 	}
     }
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-	}
-
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapdelete: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	{
-		/* this seems prudent for searches below */
-		int deref = LDAP_DEREF_NEVER;
-		ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
-	}
-
-	/* chase referrals */
-	if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
-		!= LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
-			version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return EXIT_FAILURE;
-		}
-	}
+	ld = tool_conn_setup( 0, &private_conn_setup );
 
 	if ( pw_file || want_bindpw ) {
 		if ( pw_file ) {
@@ -677,99 +141,10 @@ main( int argc, char **argv )
 		}
 	}
 
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	}
-	else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-	}
+	tool_bind( ld );
 
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
-
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
 	retval = rc = 0;
 
diff --git a/clients/tools/ldapmodify.c b/clients/tools/ldapmodify.c
index 73e9069eba..bb0ee7ffb5 100644
--- a/clients/tools/ldapmodify.c
+++ b/clients/tools/ldapmodify.c
@@ -10,9 +10,7 @@
 #include <stdio.h>
 
 #include <ac/stdlib.h>
-
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 
@@ -36,22 +34,11 @@
 #include "ldap_log.h"
 #include "ldap_pvt.h"
 
-static char	*prog;
-static char	*binddn = NULL;
-static struct berval passwd = { 0, NULL };
-static char *ldapuri = NULL;
-static char	*ldaphost = NULL;
-static int	ldapport = 0;
-#ifdef HAVE_CYRUS_SASL
-static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
-static char *sasl_realm = NULL;
-static char	*sasl_authc_id = NULL;
-static char	*sasl_authz_id = NULL;
-static char	*sasl_mech = NULL;
-static char	*sasl_secprops = NULL;
-#endif
-static int	use_tls = 0;
-static int	ldapadd, not, verbose, contoper, force;
+#include "common.h"
+
+
+static int	ldapadd, force = 0;
+static char *rejfile = NULL;
 static LDAP	*ld = NULL;
 
 #define LDAPMOD_MAXLINE		4096
@@ -77,7 +64,6 @@ static LDAP	*ld = NULL;
 #define T_NEWSUPSTR		"newsuperior"
 
 
-static void usage LDAP_P(( const char *prog )) LDAP_GCCATTR((noreturn));
 static int process_ldif_rec LDAP_P(( char *rbuf, int count ));
 static int parse_ldif_control LDAP_P(( char *line, LDAPControl ***pctrls ));
 static void addmodifyop LDAP_P((
@@ -100,8 +86,8 @@ static int dorename LDAP_P((
     LDAPControl **pctrls ));
 static char *read_one_record LDAP_P(( FILE *fp ));
 
-static void
-usage( const char *prog )
+void
+usage( void )
 {
     fprintf( stderr,
 "Add or modify entries from an LDAP server\n\n"
@@ -110,89 +96,28 @@ usage( const char *prog )
 "	specified by \"-f file\".\n"
 "Add or modify options:\n"
 "  -a         add values (default%s)\n"
-"  -c         continuous operation mode (do not stop on errors)\n"
 "  -F         force all changes records to be used\n"
 "  -S file    write skipped modifications to `file'\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -k         use Kerberos authentication\n"
-"  -K         like -k, but do only step 1 of the Kerberos bind\n"
-"  -M         enable Manage DSA IT control (-MM to make critical)\n"
-"  -n         show what would be done but don't actually update\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -P version procotol version (default: 3)\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-	     , prog, (strcmp( prog, "ldapadd" ) ? " is to replace" : "") );
-
+	         , prog, (ldapadd ? "" : " is to replace") );
+	tool_common_usage();
     exit( EXIT_FAILURE );
 }
 
 
+const char options[] = "aFrS:" "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
+
 int
-main( int argc, char **argv )
+handle_private_option( int i )
 {
-    char		*infile, *rejfile, *rbuf, *start, *rejbuf = NULL;
-    FILE		*fp, *rejfp;
-	char		*matched_msg = NULL, *error_msg = NULL;
-	int		rc, retval, i, authmethod, version, want_bindpw;
-	int		debug, manageDSAit, noop, referrals;
-	int count, len;
-	char	*pw_file = NULL;
-	char	*control, *cvalue;
-	char	*authzid = NULL;
-	int		crit;
-
-    prog = lutil_progname( "ldapmodify", argc, argv );
-
-    /* Print usage when no parameters */
-    if( argc < 2 ) usage( prog );
-
-	/* strncmp instead of strcmp since NT binaries carry .exe extension */
-    ldapadd = ( strncmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 );
-
-    infile = NULL;
-    rejfile = NULL;
-    not = verbose = want_bindpw = debug = manageDSAit = noop = referrals = 0;
-    authmethod = -1;
-	version = -1;
-
-    while (( i = getopt( argc, argv, "acrf:E:F"
-		"Cd:D:e:h:H:IkKMnO:p:P:QR:S:U:vw:WxX:y:Y:Z" )) != EOF )
-	{
-	switch( i ) {
-	/* Modify Options */
-	case 'a':	/* add */
-	    ldapadd = 1;
-	    break;
-	case 'c':	/* continuous operation */
-	    contoper = 1;
-	    break;
+	switch ( i ) {
+#if 0
+		char	*control, *cvalue;
+		int		crit;
 	case 'E': /* modify controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -211,460 +136,56 @@ main( int argc, char **argv )
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid modify control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
-	case 'f':	/* read from file */
-		if( infile != NULL ) {
-			fprintf( stderr, "%s: -f previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    infile = ber_strdup( optarg );
-	    break;
-	case 'F':	/* force all changes records to be used */
-	    force = 1;
-	    break;
-
-	/* Common Options */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = ber_strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
-
-		control = ber_strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
-
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
-
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			noop = 1 + crit;
-
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = ber_strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = ber_strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
+		usage();
 #endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return EXIT_FAILURE;
-#endif
+	case 'a':	/* add */
+	    ldapadd = 1;
 	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'M':
-		/* enable Manage DSA IT */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		manageDSAit++;
-		version = LDAP_VERSION3;
-		break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = ber_strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
+	case 'F':	/* force all changes records to be used */
+	    force = 1;
 	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
-		}
-		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
+
 	case 'r':	/* replace (obsolete) */
 		break;
 
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = ber_strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
 	case 'S':	/* skipped modifications to file */
 		if( rejfile != NULL ) {
 			fprintf( stderr, "%s: -S previously specified\n", prog );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 		rejfile = ber_strdup( optarg );
 		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = ber_strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = ber_strdup( optarg );
-		{
-			char* p;
 
-			for( p = optarg; *p != '\0'; p++ ) {
-				*p = '\0';
-			}
-		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'y':
-		pw_file = optarg;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = ber_strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = ber_strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
 	default:
-		fprintf( stderr, "%s: unrecognized option -%c\n",
-			prog, optopt );
-	    usage( prog );
+		return 0;
 	}
-    }
+	return 1;
+}
 
-	if (version == -1) {
-		version = LDAP_VERSION3;
-	}
-	if (authmethod == -1 && version > LDAP_VERSION2) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+
+int
+main( int argc, char **argv )
+{
+    char		*rbuf, *start, *rejbuf = NULL;
+    FILE		*fp, *rejfp;
+	char		*matched_msg = NULL, *error_msg = NULL;
+	int		rc, retval;
+	int count, len;
+
+    prog = lutil_progname( "ldapmodify", argc, argv );
+
+	/* strncmp instead of strcmp since NT binaries carry .exe extension */
+    ldapadd = ( strncasecmp( prog, "ldapadd", sizeof("ldapadd")-1 ) == 0 );
+
+    /* Print usage when no parameters */
+    if( argc < 2 ) usage();
+
+	tool_args( argc, argv );
 
 	if ( argc != optind )
-	usage( prog );
+	usage();
 
     if ( rejfile != NULL ) {
 	if (( rejfp = fopen( rejfile, "w" )) == NULL ) {
@@ -684,77 +205,12 @@ main( int argc, char **argv )
 	fp = stdin;
     }
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
+	if ( debug )
 		ldif_debug = debug;
-	}
 
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
+	ld = tool_conn_setup( not, 0 );
 
     if ( !not ) {
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapmodify: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	/* referrals */
-	if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-
-	if (version == -1 ) {
-		version = LDAP_VERSION3;
-	}
-
-	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
-		!= LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
-			version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return( EXIT_FAILURE );
-		}
-	}
-
 	if ( pw_file || want_bindpw ) {
 		if ( pw_file ) {
 			rc = lutil_get_filed_password( pw_file, &passwd );
@@ -765,104 +221,13 @@ main( int argc, char **argv )
 		}
 	}
 
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	}
-	else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-
-	}
-
+	tool_bind( ld );
     }
 
     rc = 0;
 
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
-
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
 	count = 0;
 	retval = 0;
diff --git a/clients/tools/ldapmodrdn.c b/clients/tools/ldapmodrdn.c
index eeedfee48a..27c2aa6792 100644
--- a/clients/tools/ldapmodrdn.c
+++ b/clients/tools/ldapmodrdn.c
@@ -24,7 +24,6 @@
 #include <ac/stdlib.h>
 
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 
@@ -33,23 +32,12 @@
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
-static char *prog = NULL;
-static char	*binddn = NULL;
-static struct berval passwd = { 0, NULL };
-static char	*ldapuri = NULL;
-static char	*ldaphost = NULL;
-static int	ldapport = 0;
-#ifdef HAVE_CYRUS_SASL
-static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
-static char *sasl_realm = NULL;
-static char	*sasl_authc_id = NULL;
-static char	*sasl_authz_id = NULL;
-static char	*sasl_mech = NULL;
-static char	*sasl_secprops = NULL;
-#endif
-static int	use_tls = 0;
-static int	not, verbose, contoper;
-static LDAP	*ld = NULL;
+#include "common.h"
+
+
+static char	*newSuperior = NULL;
+static int   remove_old_RDN = 0;
+
 
 static int domodrdn(
     LDAP	*ld,
@@ -58,8 +46,8 @@ static int domodrdn(
     char	*newSuperior,
     int		remove );	/* flag: remove old RDN */
 
-static void
-usage( const char *s )
+void
+usage( void )
 {
 	fprintf( stderr,
 "Rename LDAP entries\n\n"
@@ -68,79 +56,28 @@ usage( const char *s )
 "		If not given, the list of modifications is read from stdin or\n"
 "		from the file specified by \"-f file\" (see man page).\n"
 "Rename options:\n"
-"  -c         continuous operation mode (do not stop on errors)\n"
-"  -f file    read operations from `file'\n"
 "  -r         remove old RDN\n"
 "  -s newsup  new superior entry\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -k         use Kerberos authentication\n"
-"  -K         like -k, but do only step 1 of the Kerberos bind\n"
-"  -M         enable Manage DSA IT control (-MM to make critical)\n"
-"  -n         show what would be done but don't actually update\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -P version procotol version (default: 3)\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authzid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-,		s );
-
+	         , prog );
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
-int
-main(int argc, char **argv)
-{
-    char		*infile, *entrydn = NULL, *rdn = NULL, buf[ 4096 ];
-    FILE		*fp;
-	int		rc, retval, i, remove, havedn, authmethod, version;
-	int		want_bindpw, debug, manageDSAit, noop, crit;
-	int		referrals;
-    char	*newSuperior=NULL;
-	char	*pw_file = NULL;
-	char	*control, *cvalue;
-	char	*authzid = NULL;
-
-    infile = NULL;
-    not = contoper = verbose = remove = want_bindpw =
-		debug = manageDSAit = noop = referrals = 0;
-    authmethod = -1;
-	version = -1;
 
-    prog = lutil_progname( "ldapmodrdn", argc, argv );
+const char options[] = "rs:" "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
 
-    while (( i = getopt( argc, argv, "cf:rs:"
-		"Cd:D:e:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z" )) != EOF )
-	{
-	switch( i ) {
-	/* Modrdn Options */
-	case 'c':
-		contoper++;
-		break;
+int
+handle_private_option( int i )
+{
+	switch ( i ) {
+#if 0
+		int crit;
+		char *control, *cvalue;
 	case 'E': /* modrdn controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -159,457 +96,41 @@ main(int argc, char **argv)
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid modrdn control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
-	case 'f':	/* read from file */
-		if( infile != NULL ) {
-			fprintf( stderr, "%s: -f previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    infile = strdup( optarg );
-	    break;
+		usage();
+#endif
+
 	case 'r':	/* remove old RDN */
-	    remove++;
+	    remove_old_RDN++;
 	    break;
+
 	case 's':	/* newSuperior */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 	    newSuperior = strdup( optarg );
 	    version = LDAP_VERSION3;
 	    break;
 
-	/* Common Options */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
-
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
-
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
-
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			noop = 1 + crit;
-
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
+	default:
+		return 0;
+	}
+	return 1;
+}
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return EXIT_FAILURE;
-#endif
-	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'M':
-		/* enable Manage DSA IT */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		manageDSAit++;
-		version = LDAP_VERSION3;
-		break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
-	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
-		}
-		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = strdup( optarg );
-		{
-			char* p;
+int
+main(int argc, char **argv)
+{
+    char		*entrydn = NULL, *rdn = NULL, buf[ 4096 ];
+    FILE		*fp;
+    LDAP		*ld;
+	int		rc, retval, havedn;
 
-			for( p = optarg; *p != '\0'; p++ ) {
-				*p = '\0';
-			}
-		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'y':
-		pw_file = optarg;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	default:
-		fprintf( stderr, "%s: unrecognized option -%c\n",
-			prog, optopt );
-	    usage( prog );
-	    return( EXIT_FAILURE );
-	}
-    }
+    prog = lutil_progname( "ldapmodrdn", argc, argv );
 
-	if (version == -1) {
-		version = LDAP_VERSION3;
-	}
-	if (authmethod == -1 && version > LDAP_VERSION2) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+	tool_args( argc, argv );
 
     havedn = 0;
     if (argc - optind == 2) {
@@ -625,8 +146,7 @@ main(int argc, char **argv)
     } else if ( argc - optind != 0 ) {
 	fprintf( stderr, "%s: invalid number of arguments (%d), "
 		"only two allowed\n", prog, argc-optind );
-	usage( prog );
-	return( EXIT_FAILURE );
+	usage();
     }
 
     if ( infile != NULL ) {
@@ -638,69 +158,7 @@ main(int argc, char **argv)
 	fp = stdin;
     }
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-	}
-
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapmodify: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	/* referrals */
-	if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
-		!= LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
-			version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return( EXIT_FAILURE );
-		}
-	}
+	ld = tool_conn_setup( 0, 0 );
 
 	if ( pw_file || want_bindpw ) {
 		if ( pw_file ) {
@@ -712,103 +170,14 @@ main(int argc, char **argv)
 		}
 	}
 
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	}
-	else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-	}
-
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
+	tool_bind( ld );
 
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
     retval = rc = 0;
     if (havedn)
-	retval = domodrdn( ld, entrydn, rdn, newSuperior, remove );
+	retval = domodrdn( ld, entrydn, rdn, newSuperior, remove_old_RDN );
     else while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
 	if ( *buf != '\0' ) {	/* blank lines optional, skip */
 	    buf[ strlen( buf ) - 1 ] = '\0';	/* remove nl */
@@ -818,7 +187,7 @@ main(int argc, char **argv)
                     perror( "strdup" );
                     return( EXIT_FAILURE );
 		}
-		rc = domodrdn(ld, entrydn, rdn, newSuperior, remove );
+		rc = domodrdn(ld, entrydn, rdn, newSuperior, remove_old_RDN );
 		if ( rc != 0 )
 			retval = rc;
 		havedn = 0;
diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c
index a86d6a1136..e3f9c187e1 100644
--- a/clients/tools/ldappasswd.c
+++ b/clients/tools/ldappasswd.c
@@ -11,7 +11,6 @@
 #include <ac/stdlib.h>
 
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 #include <ac/time.h>
@@ -22,10 +21,17 @@
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
-static int	verbose = 0;
+#include "common.h"
 
-static void
-usage(const char *s)
+
+static char	*newpw = NULL;
+static char	*oldpw = NULL;
+static int   want_newpw = 0;
+static int   want_oldpw = 0;
+
+
+void
+usage( void )
 {
 	fprintf(stderr,
 "Change password of an LDAP user\n\n"
@@ -36,115 +42,26 @@ usage(const char *s)
 "  -A         prompt for old password\n"
 "  -s secret  new password\n"
 "  -S         prompt for new password\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server(s)\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -n         show what would be done but don't actually update\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-		, s );
-
+	        , prog );
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
-int
-main( int argc, char *argv[] )
-{
-	int rc;
-	char	*prog = NULL;
-	char	*ldaphost = NULL;
-	char	*ldapuri = NULL;
-
-	char	*user = NULL;
-	char	*binddn = NULL;
-
-	struct berval passwd = { 0, NULL };
-	char	*newpw = NULL;
-	char	*oldpw = NULL;
-
-	int		want_bindpw = 0;
-	int		want_newpw = 0;
-	int		want_oldpw = 0;
-
-	int		not = 0;
-	int		i;
-	int		ldapport = 0;
-	int		debug = 0;
-	int		version = -1;
-	int		authmethod = -1;
-	int		manageDSAit = 0;
-	int		noop = 0;
-	int		crit;
-	char	*control, *cvalue;
-	char	*authzid = NULL;
-
-#ifdef HAVE_CYRUS_SASL
-	unsigned	sasl_flags = LDAP_SASL_AUTOMATIC;
-	char		*sasl_realm = NULL;
-	char		*sasl_authc_id = NULL;
-	char		*sasl_authz_id = NULL;
-	char		*sasl_mech = NULL;
-	char		*sasl_secprops = NULL;
-#endif
 
-	int		use_tls = 0;
-	int		referrals = 0;
-	LDAP	       *ld = NULL;
-	struct berval *bv = NULL;
-
-	int id, code = LDAP_OTHER;
-	LDAPMessage *res;
-	char *matcheddn = NULL, *text = NULL, **refs = NULL;
-	char	*retoid = NULL;
-	struct berval *retdata = NULL;
-
-    prog = lutil_progname( "ldappasswd", argc, argv );
-
-	while( (i = getopt( argc, argv, "Aa:Ss:"
-		"Cd:D:e:h:H:InO:p:QR:U:vw:WxX:Y:Z" )) != EOF )
-	{
-		switch (i) {
-		/* Password Options */
-		case 'A':	/* prompt for old password */
-			want_oldpw++;
-			break;
-
-		case 'a':	/* old password (secret) */
-			oldpw = strdup (optarg);
-
-			{
-				char* p;
-
-				for( p = optarg; *p != '\0'; p++ ) {
-					*p = '\0';
-				}
-			}
-			break;
+const char options[] = "a:As:S" "Cd:D:e:h:H:InO:p:QR:U:vw:WxX:Y:Z";
 
+int
+handle_private_option( int i )
+{
+	switch ( i ) {
+#if 0
+		int		crit;
+		char	*control, *cvalue;
 	case 'E': /* passwd controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
+			         prog, version );
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -163,446 +80,69 @@ main( int argc, char *argv[] )
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid passwd control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
-		case 'S':	/* prompt for user password */
-			want_newpw++;
-			break;
-
-		case 's':	/* new password (secret) */
-			newpw = strdup (optarg);
-			{
-				char* p;
-
-				for( p = optarg; *p != '\0'; p++ ) {
-					*p = '\0';
-				}
-			}
-			break;
-
-	/* Common Options (including options we don't use) */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
-
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
-
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
-
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			noop = 1 + crit;
-
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
+		usage();
 #endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return EXIT_FAILURE;
-#endif
-	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
+	case 'a':	/* old password (secret) */
+		oldpw = strdup (optarg);
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'M':
-		/* enable Manage DSA IT */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		manageDSAit++;
-		version = LDAP_VERSION3;
-		break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
-	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
+		{
+			char* p;
+			for( p = optarg; *p != '\0'; p++ ) {
+				*p = '\0';
 			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
 		}
 		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
+
+	case 'A':	/* prompt for old password */
+		want_oldpw++;
 		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = strdup( optarg );
+
+	case 's':	/* new password (secret) */
+		newpw = strdup (optarg);
 		{
 			char* p;
-
 			for( p = optarg; *p != '\0'; p++ ) {
 				*p = '\0';
 			}
 		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
 		break;
 
+	case 'S':	/* prompt for user password */
+		want_newpw++;
+		break;
 
-		default:
-			fprintf( stderr, "%s: unrecognized option -%c\n",
-				prog, optopt );
-			usage (prog);
-		}
+	default:
+		return 0;
 	}
+	return 1;
+}
 
-	if (authmethod == -1) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+
+int
+main( int argc, char *argv[] )
+{
+	int rc;
+	char	*user = NULL;
+
+	LDAP	       *ld = NULL;
+	struct berval *bv = NULL;
+
+	int id, code = LDAP_OTHER;
+	LDAPMessage *res;
+	char *matcheddn = NULL, *text = NULL, **refs = NULL;
+	char	*retoid = NULL;
+	struct berval *retdata = NULL;
+
+    prog = lutil_progname( "ldappasswd", argc, argv );
+
+	/* LDAPv3 only */
+	version = LDAP_VERSION3;
+
+	tool_args( argc, argv );
 
 	if( argc - optind > 1 ) {
-		usage( prog );
+		usage();
 	} else if ( argc - optind == 1 ) {
 		user = strdup( argv[optind] );
 	} else {
@@ -643,165 +183,12 @@ main( int argc, char *argv[] )
 		passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
 	}
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-	}
+	ld = tool_conn_setup( 0, 0 );
 
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-	/* connect to server */
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapsearch: ldap_init");
-			return EXIT_FAILURE;
-		}
+	tool_bind( ld );
 
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	/* referrals */
-	if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	/* LDAPv3 only */
-	version = LDAP_VERSION3;
-	rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
-
-	if(rc != LDAP_OPT_SUCCESS ) {
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return( EXIT_FAILURE );
-		}
-	}
-
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	}
-	else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-	}
-
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
-
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
 	if( user != NULL || oldpw != NULL || newpw != NULL ) {
 		/* build change password control */
diff --git a/clients/tools/ldapsearch.c b/clients/tools/ldapsearch.c
index d5c2736c9a..a6893c5721 100644
--- a/clients/tools/ldapsearch.c
+++ b/clients/tools/ldapsearch.c
@@ -11,7 +11,6 @@
 #include <ac/stdlib.h>
 
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 #include <ac/errno.h>
@@ -35,11 +34,21 @@
 #include "ldap_defaults.h"
 #include "ldap_log.h"
 
+#include "common.h"
+
+
+static int scope = LDAP_SCOPE_SUBTREE;
+static int deref = -1;
+static int attrsonly;
+static int timelimit = -1;
+static int sizelimit = -1;
+
 static char *def_tmpdir;
 static char *def_urlpre;
 
-static void
-usage( const char *s )
+
+void
+usage( void )
 {
 	fprintf( stderr,
 "usage: %s [options] [filter [attributes...]]\nwhere:\n"
@@ -73,38 +82,8 @@ usage( const char *s )
 "  -T path    write files to directory specified by path (default: %s)\n"
 "  -u         include User Friendly entry names in the output\n"
 "  -z limit   size limit (in entries) for search\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit       (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -k         use Kerberos authentication\n"
-"  -K         like -k, but do only step 1 of the Kerberos bind\n"
-"  -M         enable Manage DSA IT control (-MM to make critical)\n"
-"  -n         show what would be done but don't actually search\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -P version procotol version (default: 3)\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-, s, def_urlpre, def_tmpdir );
-
+	         , prog, def_urlpre, def_tmpdir );
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
@@ -154,24 +133,12 @@ static int dosearch LDAP_P((
 
 static char *tmpdir = NULL;
 static char *urlpre = NULL;
-static char *prog = NULL;
-static char	*binddn = NULL;
-static struct berval passwd = { 0, NULL };
 static char	*base = NULL;
-static char	*ldaphost = NULL;
-static char *ldapuri = NULL;
-static int	ldapport = 0;
-#ifdef HAVE_CYRUS_SASL
-static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
-static char	*sasl_realm = NULL;
-static char	*sasl_authc_id = NULL;
-static char	*sasl_authz_id = NULL;
-static char	*sasl_mech = NULL;
-static char	*sasl_secprops = NULL;
-#endif
-static int	use_tls = 0;
 static char	*sortattr = NULL;
-static int	verbose, not, includeufn, vals2tmp, ldif;
+static int  includeufn, vals2tmp = 0, ldif = 0;
+
+static int subentries = 0, valuesReturnFilter = 0;
+static char	*vrFilter = NULL;
 
 static int pagedResults = 0;
 static ber_int_t pageSize = 0;
@@ -202,68 +169,16 @@ urlize(char *url)
 	}
 }
 
-int
-main( int argc, char **argv )
-{
-	char		*infile, *filtpattern, **attrs = NULL, line[BUFSIZ];
-	FILE		*fp = NULL;
-	int			rc, i, first, scope, deref, attrsonly, manageDSAit, noop, crit;
-	int			referrals, timelimit, sizelimit, debug;
-	int		authmethod, version, want_bindpw;
-	LDAP		*ld = NULL;
-	BerElement	*ber = NULL;
-	char	*control = NULL, *cvalue;
-	int		subentries, valuesReturnFilter;
-	struct berval 	*sebvalp = NULL, *vrbvalp = NULL;
-	char	*vrFilter  = NULL;
-	char	*pw_file = NULL;
-	char	*authzid = NULL;
-	struct berval	*prbvalp = NULL;
-
-	infile = NULL;
-	debug = verbose = not = vals2tmp = referrals =
-		subentries = valuesReturnFilter =
-		attrsonly = manageDSAit = noop = ldif = want_bindpw = 0;
 
-	npagedresponses = npagedentries = npagedreferences =
-		npagedextended = npagedpartial = 0;
-
-	prog = lutil_progname( "ldapsearch", argc, argv );
-
-	lutil_log_initialize(argc, argv);
+const char options[] = "a:Ab:E:F:l:Ls:S:tT:uz:"
+                       "Cd:D:e:f:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
 
-	deref = sizelimit = timelimit = version = -1;
-
-	scope = LDAP_SCOPE_SUBTREE;
-	authmethod = -1;
-
-	if((def_tmpdir = getenv("TMPDIR")) == NULL &&
-	   (def_tmpdir = getenv("TMP")) == NULL &&
-	   (def_tmpdir = getenv("TEMP")) == NULL )
-	{
-		def_tmpdir = LDAP_TMPDIR;
-	}
-
-	if ( !*def_tmpdir )
-		def_tmpdir = LDAP_TMPDIR;
-
-	def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
-
-	if( def_urlpre == NULL ) {
-		perror( "malloc" );
-		return EXIT_FAILURE;
-	}
-
-	sprintf( def_urlpre, "file:///%s/",
-		def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
-
-	urlize( def_urlpre );
-
-	while (( i = getopt( argc, argv, "Aa:b:E:F:f:Ll:S:s:T:tuz:"
-		"Cd:e:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z")) != EOF )
-	{
-	switch( i ) {
-	/* Search Options */
+int
+handle_private_option( int i )
+{
+	int crit;
+	char *control, *cvalue;
+	switch ( i ) {
 	case 'a':	/* set alias deref option */
 		if ( strcasecmp( optarg, "never" ) == 0 ) {
 		deref = LDAP_DEREF_NEVER;
@@ -275,7 +190,7 @@ main( int argc, char **argv )
 		deref = LDAP_DEREF_ALWAYS;
 		} else {
 		fprintf( stderr, "alias deref should be never, search, find, or always\n" );
-		usage(prog);
+		usage();
 		}
 		break;
 	case 'A':	/* retrieve attribute names only -- no values */
@@ -288,7 +203,7 @@ main( int argc, char **argv )
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -311,14 +226,14 @@ main( int argc, char **argv )
 			/* ValuesReturnFilter control */
 			if( valuesReturnFilter ) {
 				fprintf( stderr, "ValuesReturnFilter previously specified\n");
-				return EXIT_FAILURE;
+				exit( EXIT_FAILURE );
 			}
 			valuesReturnFilter= 1 + crit;
 
 			if ( cvalue == NULL ) {
 				fprintf( stderr,
 					"missing filter in ValuesReturnFilter control\n");
-				return EXIT_FAILURE;
+				exit( EXIT_FAILURE );
 			}
 
 			vrFilter = cvalue;
@@ -329,13 +244,13 @@ main( int argc, char **argv )
 			/* PagedResults control */
 			if ( pagedResults != 0 ) {
 				fprintf( stderr, "PagedResultsControl previously specified\n" );
-				return EXIT_FAILURE;
+				exit( EXIT_FAILURE );
 			}
 			
 			num = sscanf( cvalue, "%d", &tmp );
 			if ( num != 1 ) {
 				fprintf( stderr, "Invalid value for PagedResultsControl, %s.\n", cvalue);
-				return EXIT_FAILURE;
+				exit( EXIT_FAILURE );
 
 			}
 			pageSize = (ber_int_t) tmp;
@@ -345,7 +260,7 @@ main( int argc, char **argv )
 		} else if ( strcasecmp( control, "subentries" ) == 0 ) {
 			if( subentries ) {
 				fprintf( stderr, "subentries control previously specified\n");
-				return EXIT_FAILURE;
+				exit( EXIT_FAILURE );
 			}
 			if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) {
 				subentries = 2;
@@ -353,26 +268,18 @@ main( int argc, char **argv )
 				subentries = 1;
 			} else {
 				fprintf( stderr,
-					"subentries control value \"%s\" invalid\n");
-				return EXIT_FAILURE;
+					"subentries control value \"%s\" invalid\n",
+					cvalue );
+				exit( EXIT_FAILURE );
 			}
 			if( crit ) subentries *= -1;
 #endif
 
 		} else {
 			fprintf( stderr, "Invalid control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
+			usage();
 		}
 		break;
-
-	case 'f':	/* input file */
-		if( infile != NULL ) {
-			fprintf( stderr, "%s: -f previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		infile = strdup( optarg );
-		break;
 	case 'F':	/* uri prefix */
 		if( urlpre ) free( urlpre );
 		urlpre = strdup( optarg );
@@ -382,7 +289,7 @@ main( int argc, char **argv )
 		if( timelimit < 0 ) {
 			fprintf( stderr, "%s: invalid timelimit (%d) specified\n",
 				prog, timelimit );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 		break;
 	case 'L':	/* print entries in LDIF format */
@@ -397,15 +304,12 @@ main( int argc, char **argv )
 		scope = LDAP_SCOPE_SUBTREE;
 		} else {
 		fprintf( stderr, "scope should be base, one, or sub\n" );
-		usage(prog);
+		usage();
 		}
 		break;
 	case 'S':	/* sort attribute */
 		sortattr = strdup( optarg );
 		break;
-	case 'u':	/* include UFN */
-		++includeufn;
-		break;
 	case 't':	/* write attribute values to TMPDIR files */
 		++vals2tmp;
 		break;
@@ -413,438 +317,84 @@ main( int argc, char **argv )
 		if( tmpdir ) free( tmpdir );
 		tmpdir = strdup( optarg );
 		break;
+	case 'u':	/* include UFN */
+		++includeufn;
+		break;
 	case 'z':	/* size limit */
 		sizelimit = atoi( optarg );
 		break;
+	default:
+		return 0;
+	}
+	return 1;
+}
 
-	/* Common Options */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
 
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
+static void
+private_conn_setup( LDAP *ld )
+{
+	if (deref != -1 &&
+		ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS )
+	{
+		fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref );
+		exit( EXIT_FAILURE );
+	}
+	if (timelimit != -1 &&
+		ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
+	{
+		fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
+		exit( EXIT_FAILURE );
+	}
+	if (sizelimit != -1 &&
+		ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
+	{
+		fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
+		exit( EXIT_FAILURE );
+	}
+}
 
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
 
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
+int
+main( int argc, char **argv )
+{
+	char		*filtpattern, **attrs = NULL, line[BUFSIZ];
+	FILE		*fp = NULL;
+	int			rc, i, first;
+	LDAP		*ld = NULL;
+	BerElement	*ber = NULL;
+	struct berval 	*sebvalp = NULL, *vrbvalp = NULL;
+	struct berval	*prbvalp = NULL;
 
-			assert( authzid == NULL );
-			authzid = cvalue;
+	npagedresponses = npagedentries = npagedreferences =
+		npagedextended = npagedpartial = 0;
 
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
+	prog = lutil_progname( "ldapsearch", argc, argv );
 
-			manageDSAit = 1 + crit;
+	lutil_log_initialize(argc, argv);
 
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
+	if((def_tmpdir = getenv("TMPDIR")) == NULL &&
+	   (def_tmpdir = getenv("TMP")) == NULL &&
+	   (def_tmpdir = getenv("TEMP")) == NULL )
+	{
+		def_tmpdir = LDAP_TMPDIR;
+	}
 
-			noop = 1 + crit;
+	if ( !*def_tmpdir )
+		def_tmpdir = LDAP_TMPDIR;
 
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
+	def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
+	if( def_urlpre == NULL ) {
+		perror( "malloc" );
 		return EXIT_FAILURE;
-#endif
-	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
+	}
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'M':
-		/* enable Manage DSA IT */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		manageDSAit++;
-		version = LDAP_VERSION3;
-		break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
-	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
-		}
-		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = strdup( optarg );
-		{
-			char* p;
+	sprintf( def_urlpre, "file:///%s/",
+		def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
 
-			for( p = optarg; *p != '\0'; p++ ) {
-				*p = '\0';
-			}
-		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'y':
-		pw_file = optarg;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	default:
-		fprintf( stderr, "%s: unrecognized option -%c\n",
-			prog, optopt );
-		usage(prog);
-	}
-	}
+	urlize( def_urlpre );
 
-	if (version == -1) {
-		version = LDAP_VERSION3;
-	}
-	if (authmethod == -1 && version > LDAP_VERSION2) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+	tool_args( argc, argv );
 
 	if (( argc - optind < 1 ) ||
 		( *argv[optind] != '(' /*')'*/ &&
@@ -889,93 +439,10 @@ main( int argc, char **argv )
 		urlize( urlpre );
 	}
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
+	if ( debug )
 		ldif_debug = debug;
-	}
-
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapsearch: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	if (deref != -1 &&
-		ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_DEREF %d\n", deref );
-		return EXIT_FAILURE;
-	}
-	if (timelimit != -1 &&
-		ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
-		return EXIT_FAILURE;
-	}
-	if (sizelimit != -1 &&
-		ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
-		return EXIT_FAILURE;
-	}
 
-	/* referrals */
-	if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	if (version == -1 ) {
-		version = LDAP_VERSION3;
-	}
-
-	if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
-		!= LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
-			version );
-		return EXIT_FAILURE;
-	}
-
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return EXIT_FAILURE;
-		}
-	}
+	ld = tool_conn_setup( 0, &private_conn_setup );
 
 	if ( pw_file || want_bindpw ) {
 		if ( pw_file ) {
@@ -987,49 +454,7 @@ main( int argc, char **argv )
 		}
 	}
 
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog);
-		return( EXIT_FAILURE );
-#endif
-	} else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-	}
+	tool_bind( ld );
 
 getNextPage:
 	if ( manageDSAit || noop || subentries
@@ -1037,42 +462,7 @@ getNextPage:
 	{
 		int err;
 		int i=0;
-		int crit = 0;
-		LDAPControl c[6];
-		LDAPControl *ctrls[7];
-		
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
+		LDAPControl c[3];
 
 #ifdef LDAP_CONTROL_SUBENTRIES
 		if ( subentries ) {
@@ -1094,10 +484,7 @@ getNextPage:
 			c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES;
 			c[i].ldctl_value=(*sebvalp);
 			c[i].ldctl_iscritical = subentries < 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
+			i++;
 		}
 #endif
 
@@ -1121,10 +508,7 @@ getNextPage:
 			c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
 			c[i].ldctl_value=(*vrbvalp);
 			c[i].ldctl_iscritical = valuesReturnFilter > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
+			i++;
 		}
 
 		if ( pagedResults ) {
@@ -1142,21 +526,10 @@ getNextPage:
 			c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
 			c[i].ldctl_value=(*prbvalp);
 			c[i].ldctl_iscritical = pagedResults > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
+			i++;
 		}
 
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
+		tool_server_controls( ld, c, i );
 
 		ber_bvfree( sebvalp );
 		ber_bvfree( vrbvalp );
diff --git a/clients/tools/ldapwhoami.c b/clients/tools/ldapwhoami.c
index 5e2736f9f8..322e8cc5b9 100644
--- a/clients/tools/ldapwhoami.c
+++ b/clients/tools/ldapwhoami.c
@@ -11,7 +11,6 @@
 #include <ac/stdlib.h>
 
 #include <ac/ctype.h>
-#include <ac/signal.h>
 #include <ac/socket.h>
 #include <ac/string.h>
 #include <ac/time.h>
@@ -22,99 +21,35 @@
 #include "lutil_ldap.h"
 #include "ldap_defaults.h"
 
-static int	verbose = 0;
+#include "common.h"
 
-static void
-usage(const char *s)
+
+void
+usage( void )
 {
 	fprintf(stderr,
 "Issue LDAP Who am I? operation to request user's authzid\n\n"
 "usage: %s [options]\n"
-
-"Common options:\n"
-"  -d level   set LDAP debugging level to `level'\n"
-"  -D binddn  bind DN\n"
-"  -e [!]<ctrl>[=<ctrlparam>] general controls (! indicates criticality)\n"
-"             [!]authzid=<authzid> (\"dn:<dn>\" or \"u:<user>\")\n"
-"             [!]manageDSAit   (alternate form, see -M)\n"
-"             [!]noop\n"
-"  -f file    read operations from `file'\n"
-"  -h host    LDAP server(s)\n"
-"  -H URI     LDAP Uniform Resource Indentifier(s)\n"
-"  -I         use SASL Interactive mode\n"
-"  -n         show what would be done but don't actually do it\n"
-"  -O props   SASL security properties\n"
-"  -p port    port on LDAP server\n"
-"  -Q         use SASL Quiet mode\n"
-"  -R realm   SASL realm\n"
-"  -U authcid SASL authentication identity\n"
-"  -v         run in verbose mode (diagnostics to standard output)\n"
-"  -w passwd  bind passwd (for simple authentication)\n"
-"  -W         prompt for bind passwd\n"
-"  -x         Simple authentication\n"
-"  -X authzid SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
-"  -y file    Read passwd from file\n"
-"  -Y mech    SASL mechanism\n"
-"  -Z         Start TLS request (-ZZ to require successful response)\n"
-		, s );
-
+	        , prog);
+	tool_common_usage();
 	exit( EXIT_FAILURE );
 }
 
-int
-main( int argc, char *argv[] )
-{
-	int rc;
-	char	*prog = NULL;
-	char	*ldaphost = NULL;
-	char	*ldapuri = NULL;
 
-	char	*user = NULL;
-	char	*binddn = NULL;
-
-	struct berval passwd = { 0, NULL };
-
-	char	*pw_file = NULL;
-	int		want_bindpw = 0;
-
-	int		not = 0;
-	int		i;
-	int		ldapport = 0;
-	int		debug = 0;
-	int		version = -1;
-	int		authmethod = -1;
-#ifdef HAVE_CYRUS_SASL
-	unsigned	sasl_flags = LDAP_SASL_AUTOMATIC;
-	char		*sasl_realm = NULL;
-	char		*sasl_authc_id = NULL;
-	char		*sasl_authz_id = NULL;
-	char		*sasl_mech = NULL;
-	char		*sasl_secprops = NULL;
-#endif
-	int		use_tls = 0;
-	int		referrals = 0;
-	LDAP	       *ld = NULL;
-	int	manageDSAit=0;
-	int noop=0;
-	char *authzid = NULL;
-	char	*control, *cvalue;
-	int		crit;
+const char options[] = "Cd:D:e:h:H:InO:p:QR:U:vw:WxX:y:Y:Z";
 
-	char *matcheddn = NULL, *text = NULL, **refs = NULL;
-	char	*retoid = NULL;
-	struct berval *retdata = NULL;
-
-	prog = lutil_progname( "ldapwhoami", argc, argv );
-
-	while( (i = getopt( argc, argv, 
-		"Cd:D:e:h:H:InO:p:QR:U:vw:WxX:y:Y:Z" )) != EOF )
-	{
-		switch (i) {
+int
+handle_private_option( int i )
+{
+	switch ( i ) {
+#if 0
+		char	*control, *cvalue;
+		int		crit;
 	case 'E': /* whoami controls */
 		if( version == LDAP_VERSION2 ) {
 			fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
 				prog, version );
-			return EXIT_FAILURE;
+			exit( EXIT_FAILURE );
 		}
 
 		/* should be extended to support comma separated list of
@@ -133,429 +68,37 @@ main( int argc, char *argv[] )
 			*cvalue++ = '\0';
 		}
 		fprintf( stderr, "Invalid whoami control name: %s\n", control );
-		usage(prog);
-		return EXIT_FAILURE;
-
-	/* Common Options (including options we don't use) */
-	case 'C':
-		referrals++;
-		break;
-	case 'd':
-	    debug |= atoi( optarg );
-	    break;
-	case 'D':	/* bind DN */
-		if( binddn != NULL ) {
-			fprintf( stderr, "%s: -D previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    binddn = strdup( optarg );
-	    break;
-	case 'e': /* general controls */
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -e incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-
-		/* should be extended to support comma separated list of
-		 *	[!]key[=value] parameters, e.g.  -e !foo,bar=567
-		 */
-
-		crit = 0;
-		cvalue = NULL;
-		if( optarg[0] == '!' ) {
-			crit = 1;
-			optarg++;
-		}
-
-		control = strdup( optarg );
-		if ( (cvalue = strchr( control, '=' )) != NULL ) {
-			*cvalue++ = '\0';
-		}
-
-		if ( strcasecmp( control, "authzid" ) == 0 ) {
-			if( authzid != NULL ) {
-				fprintf( stderr, "authzid control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue == NULL ) {
-				fprintf( stderr, "authzid: control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-			if( !crit ) {
-				fprintf( stderr, "authzid: must be marked critical\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			assert( authzid == NULL );
-			authzid = cvalue;
-
-		} else if ( strcasecmp( control, "manageDSAit" ) == 0 ) {
-			if( manageDSAit ) {
-				fprintf( stderr, "manageDSAit control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "manageDSAit: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
-
-			manageDSAit = 1 + crit;
+		usage();
+#endif
 
-		} else if ( strcasecmp( control, "noop" ) == 0 ) {
-			if( noop ) {
-				fprintf( stderr, "noop control previously specified\n");
-				return EXIT_FAILURE;
-			}
-			if( cvalue != NULL ) {
-				fprintf( stderr, "noop: no control value expected\n" );
-				usage(prog);
-				return EXIT_FAILURE;
-			}
+	default:
+		return 0;
+	}
+	return 1;
+}
 
-			noop = 1 + crit;
 
-		} else {
-			fprintf( stderr, "Invalid general control name: %s\n", control );
-			usage(prog);
-			return EXIT_FAILURE;
-		}
-		break;
-	case 'h':	/* ldap host */
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -h incompatible with -H\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -h previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldaphost = strdup( optarg );
-	    break;
-	case 'H':	/* ldap URI */
-		if( ldaphost != NULL ) {
-			fprintf( stderr, "%s: -H incompatible with -h\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapport ) {
-			fprintf( stderr, "%s: -H incompatible with -p\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( ldapuri != NULL ) {
-			fprintf( stderr, "%s: -H previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapuri = strdup( optarg );
-	    break;
-	case 'I':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -I incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_INTERACTIVE;
-		break;
-#else
-		fprintf( stderr, "%s: was not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'k':	/* kerberos bind */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
+int
+main( int argc, char *argv[] )
+{
+	int rc;
+	char	*user = NULL;
 
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: -k incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-			
-		authmethod = LDAP_AUTH_KRBV4;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return EXIT_FAILURE;
-#endif
-	    break;
-	case 'K':	/* kerberos bind, part one only */
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
-		if( version > LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
+	LDAP	       *ld = NULL;
 
-		authmethod = LDAP_AUTH_KRBV41;
-#else
-		fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
-		return( EXIT_FAILURE );
-#endif
-	    break;
-	case 'n':	/* print deletes, don't actually do them */
-	    ++not;
-	    break;
-	case 'O':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_secprops != NULL ) {
-			fprintf( stderr, "%s: -O previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_secprops = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'p':
-		if( ldapport ) {
-			fprintf( stderr, "%s: -p previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-	    ldapport = atoi( optarg );
-	    break;
-	case 'P':
-		switch( atoi(optarg) ) {
-		case 2:
-			if( version == LDAP_VERSION3 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION2;
-			break;
-		case 3:
-			if( version == LDAP_VERSION2 ) {
-				fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
-					prog, version );
-				return EXIT_FAILURE;
-			}
-			version = LDAP_VERSION3;
-			break;
-		default:
-			fprintf( stderr, "%s: protocol version should be 2 or 3\n",
-				prog );
-			usage( prog );
-			return( EXIT_FAILURE );
-		}
-		break;
-	case 'Q':
-#ifdef HAVE_CYRUS_SASL
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Q incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_flags = LDAP_SASL_QUIET;
-		break;
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	case 'R':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_realm != NULL ) {
-			fprintf( stderr, "%s: -R previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -R incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_realm = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'U':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authc_id != NULL ) {
-			fprintf( stderr, "%s: -U previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -U incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible previous "
-				"authentication choice\n",
-				prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authc_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'v':	/* verbose mode */
-	    verbose++;
-	    break;
-	case 'w':	/* password */
-	    passwd.bv_val = strdup( optarg );
-		{
-			char* p;
-
-			for( p = optarg; *p != '\0'; p++ ) {
-				*p = '\0';
-			}
-		}
-		passwd.bv_len = strlen( passwd.bv_val );
-	    break;
-	case 'W':
-		want_bindpw++;
-		break;
-	case 'y':
-		pw_file = optarg;
-		break;
-	case 'Y':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_mech != NULL ) {
-			fprintf( stderr, "%s: -Y previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Y incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_mech = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'x':
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
-			fprintf( stderr, "%s: incompatible with previous "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SIMPLE;
-		break;
-	case 'X':
-#ifdef HAVE_CYRUS_SASL
-		if( sasl_authz_id != NULL ) {
-			fprintf( stderr, "%s: -X previously specified\n", prog );
-			return EXIT_FAILURE;
-		}
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
-			fprintf( stderr, "%s: -X incompatible with "
-				"authentication choice\n", prog );
-			return EXIT_FAILURE;
-		}
-		authmethod = LDAP_AUTH_SASL;
-		version = LDAP_VERSION3;
-		sasl_authz_id = strdup( optarg );
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
-	case 'Z':
-#ifdef HAVE_TLS
-		if( version == LDAP_VERSION2 ) {
-			fprintf( stderr, "%s: -Z incompatible with version %d\n",
-				prog, version );
-			return EXIT_FAILURE;
-		}
-		version = LDAP_VERSION3;
-		use_tls++;
-#else
-		fprintf( stderr, "%s: not compiled with TLS support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-		break;
+	char *matcheddn = NULL, *text = NULL, **refs = NULL;
+	char	*retoid = NULL;
+	struct berval *retdata = NULL;
 
+	prog = lutil_progname( "ldapwhoami", argc, argv );
 
-		default:
-			fprintf( stderr, "%s: unrecognized option -%c\n",
-				prog, optopt );
-			usage (prog);
-		}
-	}
+	/* LDAPv3 only */
+	version = LDAP_VERSION3;
 
-	if (authmethod == -1) {
-#ifdef HAVE_CYRUS_SASL
-		authmethod = LDAP_AUTH_SASL;
-#else
-		authmethod = LDAP_AUTH_SIMPLE;
-#endif
-	}
+	tool_args( argc, argv );
 
 	if( argc - optind > 1 ) {
-		usage( prog );
+		usage();
 	} else if ( argc - optind == 1 ) {
 		user = strdup( argv[optind] );
 	} else {
@@ -572,170 +115,17 @@ main( int argc, char *argv[] )
 		}
 	}
 
-	if ( debug ) {
-		if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-		if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
-		}
-	}
-
-#ifdef SIGPIPE
-	(void) SIGNAL( SIGPIPE, SIG_IGN );
-#endif
-
-	/* connect to server */
-	if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_init( %s, %d )\n",
-				ldaphost != NULL ? ldaphost : "<DEFAULT>",
-				ldapport );
-		}
-
-		ld = ldap_init( ldaphost, ldapport );
-		if( ld == NULL ) {
-			perror("ldapwhoami: ldap_init");
-			return EXIT_FAILURE;
-		}
-
-	} else {
-		if ( verbose ) {
-			fprintf( stderr, "ldap_initialize( %s )\n",
-				ldapuri != NULL ? ldapuri : "<DEFAULT>" );
-		}
-
-		rc = ldap_initialize( &ld, ldapuri );
-		if( rc != LDAP_SUCCESS ) {
-			fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
-				rc, ldap_err2string(rc) );
-			return EXIT_FAILURE;
-		}
-	}
-
-	/* referrals */
-	if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
-		referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
-	{
-		fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
-			referrals ? "on" : "off" );
-		return EXIT_FAILURE;
-	}
-
-	/* LDAPv3 only */
-	version = LDAP_VERSION3;
-	rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
-
-	if(rc != LDAP_OPT_SUCCESS ) {
-		fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
-		return EXIT_FAILURE;
-	}
+	ld = tool_conn_setup( 0, 0 );
 
-	if ( use_tls && ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS )) {
-		ldap_perror( ld, "ldap_start_tls" );
-		if ( use_tls > 1 ) {
-			return( EXIT_FAILURE );
-		}
-	}
-
-	if ( authmethod == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-		void *defaults;
-
-		if( sasl_secprops != NULL ) {
-			rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
-				(void *) sasl_secprops );
-			
-			if( rc != LDAP_OPT_SUCCESS ) {
-				fprintf( stderr,
-					"Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
-					sasl_secprops );
-				return( EXIT_FAILURE );
-			}
-		}
-		
-		defaults = lutil_sasl_defaults( ld,
-			sasl_mech,
-			sasl_realm,
-			sasl_authc_id,
-			passwd.bv_val,
-			sasl_authz_id );
-
-		rc = ldap_sasl_interactive_bind_s( ld, binddn,
-			sasl_mech, NULL, NULL,
-			sasl_flags, lutil_sasl_interact, defaults );
-
-		if( rc != LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
-			return( EXIT_FAILURE );
-		}
-#else
-		fprintf( stderr, "%s: not compiled with SASL support\n",
-			prog );
-		return( EXIT_FAILURE );
-#endif
-	}
-	else {
-		if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
-				!= LDAP_SUCCESS ) {
-			ldap_perror( ld, "ldap_bind" );
-			return( EXIT_FAILURE );
-		}
-	}
+	tool_bind( ld );
 
 	if ( not ) {
 		rc = LDAP_SUCCESS;
 		goto skip;
 	}
 
-	if ( authzid || manageDSAit || noop ) {
-		int err, crit=0, i=0;
-		LDAPControl c[3];
-		LDAPControl *ctrls[4];
-
-		if ( authzid ) {
-			c[i].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
-			c[i].ldctl_value.bv_val = authzid;
-			c[i].ldctl_value.bv_len = strlen( authzid );
-			c[i].ldctl_iscritical = 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( manageDSAit ) {
-			c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = manageDSAit > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-
-		if ( noop ) {
-			c[i].ldctl_oid = LDAP_CONTROL_NOOP;
-			c[i].ldctl_value.bv_val = NULL;
-			c[i].ldctl_value.bv_len = 0;
-			c[i].ldctl_iscritical = noop > 1;
-
-			if( c[i].ldctl_iscritical ) crit++;
-			ctrls[i] = &c[i];
-			ctrls[++i] = NULL;
-		}
-	
-		err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
-
-		if( err != LDAP_OPT_SUCCESS ) {
-			fprintf( stderr, "Could not set %scontrols\n",
-				crit ? "critical " : "" );
-			if ( crit ) {
-				return EXIT_FAILURE;
-			}
-		}
-	}
+	if ( authzid || manageDSAit || noop )
+		tool_server_controls( ld, NULL, 0 );
 
 	rc = ldap_whoami_s( ld, &retdata, NULL, NULL ); 
 
-- 
GitLab