Home | History | Annotate | Line # | Download | only in tools
ldapsearch.c revision 1.3
      1 /*	$NetBSD: ldapsearch.c,v 1.3 2021/08/14 16:14:49 christos Exp $	*/
      2 
      3 /* ldapsearch -- a tool for searching LDAP directories */
      4 /* $OpenLDAP$ */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 1998-2021 The OpenLDAP Foundation.
      8  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
      9  * Portions Copyright 1998-2001 Net Boolean Incorporated.
     10  * Portions Copyright 2001-2003 IBM Corporation.
     11  * All rights reserved.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted only as authorized by the OpenLDAP
     15  * Public License.
     16  *
     17  * A copy of this license is available in the file LICENSE in the
     18  * top-level directory of the distribution or, alternatively, at
     19  * <http://www.OpenLDAP.org/license.html>.
     20  */
     21 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
     22  * All rights reserved.
     23  *
     24  * Redistribution and use in source and binary forms are permitted
     25  * provided that this notice is preserved and that due credit is given
     26  * to the University of Michigan at Ann Arbor.  The name of the
     27  * University may not be used to endorse or promote products derived
     28  * from this software without specific prior written permission.  This
     29  * software is provided ``as is'' without express or implied warranty.
     30  */
     31 /* ACKNOWLEDGEMENTS:
     32  * This work was originally developed by the University of Michigan
     33  * (as part of U-MICH LDAP).  Additional significant contributors
     34  * include:
     35  *   Jong Hyuk Choi
     36  *   Lynn Moss
     37  *   Mikhail Sahalaev
     38  *   Kurt D. Zeilenga
     39  */
     40 
     41 #include <sys/cdefs.h>
     42 __RCSID("$NetBSD: ldapsearch.c,v 1.3 2021/08/14 16:14:49 christos Exp $");
     43 
     44 #include "portable.h"
     45 
     46 #include <stdio.h>
     47 
     48 #include <ac/stdlib.h>
     49 #include <ac/ctype.h>
     50 #include <ac/string.h>
     51 #include <ac/unistd.h>
     52 #include <ac/errno.h>
     53 #include <ac/time.h>
     54 
     55 #include <sys/stat.h>
     56 
     57 #include <ac/signal.h>
     58 
     59 #ifdef HAVE_FCNTL_H
     60 #include <fcntl.h>
     61 #endif
     62 #ifdef HAVE_SYS_TYPES_H
     63 #include <sys/types.h>
     64 #endif
     65 #ifdef HAVE_IO_H
     66 #include <io.h>
     67 #endif
     68 
     69 #include <ldap.h>
     70 
     71 #include "ldif.h"
     72 #include "lutil.h"
     73 #include "lutil_ldap.h"
     74 #include "ldap_defaults.h"
     75 #include "ldap_pvt.h"
     76 
     77 #include "common.h"
     78 
     79 #if !LDAP_DEPRECATED
     80 /*
     81  * NOTE: we use this deprecated function only because
     82  * we want ldapsearch to provide some client-side sorting
     83  * capability.
     84  */
     85 /* from ldap.h */
     86 typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */
     87 	LDAP_CONST char *left,
     88 	LDAP_CONST char *right ));
     89 
     90 LDAP_F( int )	/* deprecated */
     91 ldap_sort_entries LDAP_P(( LDAP *ld,
     92 	LDAPMessage **chain,
     93 	LDAP_CONST char *attr,
     94 	LDAP_SORT_AD_CMP_PROC *cmp ));
     95 #endif
     96 
     97 static int scope = LDAP_SCOPE_SUBTREE;
     98 static int deref = -1;
     99 static int attrsonly;
    100 static int timelimit = -1;
    101 static int sizelimit = -1;
    102 
    103 static char *control;
    104 
    105 static char *def_tmpdir;
    106 static char *def_urlpre;
    107 
    108 #if defined(__CYGWIN__) || defined(__MINGW32__)
    109 /* Turn off commandline globbing, otherwise you cannot search for
    110  * attribute '*'
    111  */
    112 int _CRT_glob = 0;
    113 #endif
    114 
    115 void
    116 usage( void )
    117 {
    118 	fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog);
    119 	fprintf( stderr, _("  filter\tRFC 4515 compliant LDAP search filter\n"));
    120 	fprintf( stderr, _("  attributes\twhitespace-separated list of attribute descriptions\n"));
    121 	fprintf( stderr, _("    which may include:\n"));
    122 	fprintf( stderr, _("      1.1   no attributes\n"));
    123 	fprintf( stderr, _("      *     all user attributes\n"));
    124 	fprintf( stderr, _("      +     all operational attributes\n"));
    125 
    126 
    127 	fprintf( stderr, _("Search options:\n"));
    128 	fprintf( stderr, _("  -a deref   one of never (default), always, search, or find\n"));
    129 	fprintf( stderr, _("  -A         retrieve attribute names only (no values)\n"));
    130 	fprintf( stderr, _("  -b basedn  base dn for search\n"));
    131 	fprintf( stderr, _("  -c         continuous operation mode (do not stop on errors)\n"));
    132 	fprintf( stderr, _("  -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n"));
    133 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
    134 	fprintf( stderr, _("             [!]accountUsability         (NetScape Account usability)\n"));
    135 #endif
    136 	fprintf( stderr, _("             [!]domainScope              (domain scope)\n"));
    137 	fprintf( stderr, _("             !dontUseCopy                (Don't Use Copy)\n"));
    138 	fprintf( stderr, _("             [!]mv=<filter>              (RFC 3876 matched values filter)\n"));
    139 	fprintf( stderr, _("             [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
    140 	fprintf( stderr, _("             [!]ps=<changetypes>/<changesonly>/<echg> (draft persistent search)\n"));
    141 	fprintf( stderr, _("             [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
    142 	fprintf( stderr, _("                                         (RFC 2891 server side sorting)\n"));
    143 	fprintf( stderr, _("             [!]subentries[=true|false]  (RFC 3672 subentries)\n"));
    144 	fprintf( stderr, _("             [!]sync=ro[/<cookie>]       (RFC 4533 LDAP Sync refreshOnly)\n"));
    145 	fprintf( stderr, _("                     rp[/<cookie>][/<slimit>] (refreshAndPersist)\n"));
    146 	fprintf( stderr, _("             [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n"));
    147 	fprintf( stderr, _("                                         (ldapv3-vlv-09 virtual list views)\n"));
    148 #ifdef LDAP_CONTROL_X_DEREF
    149 	fprintf( stderr, _("             [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
    150 #endif
    151 #ifdef LDAP_CONTROL_X_DIRSYNC
    152 	fprintf( stderr, _("             !dirSync=<flags>/<maxAttrCount>[/<cookie>]\n"));
    153 	fprintf( stderr, _("                                         (MS AD DirSync)\n"));
    154 #endif
    155 #ifdef LDAP_CONTROL_X_EXTENDED_DN
    156 	fprintf( stderr, _("             [!]extendedDn=<flag>        (MS AD Extended DN\n"));
    157 #endif
    158 #ifdef LDAP_CONTROL_X_SHOW_DELETED
    159 	fprintf( stderr, _("             [!]showDeleted              (MS AD Show Deleted)\n"));
    160 #endif
    161 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
    162 	fprintf( stderr, _("             [!]serverNotif              (MS AD Server Notification)\n"));
    163 #endif
    164 	fprintf( stderr, _("             [!]<oid>[=:<value>|::<b64value>] (generic control; no response handling)\n"));
    165 	fprintf( stderr, _("  -f file    read operations from `file'\n"));
    166 	fprintf( stderr, _("  -F prefix  URL prefix for files (default: %s)\n"), def_urlpre);
    167 	fprintf( stderr, _("  -l limit   time limit (in seconds, or \"none\" or \"max\") for search\n"));
    168 	fprintf( stderr, _("  -L         print responses in LDIFv1 format\n"));
    169 	fprintf( stderr, _("  -LL        print responses in LDIF format without comments\n"));
    170 	fprintf( stderr, _("  -LLL       print responses in LDIF format without comments\n"));
    171 	fprintf( stderr, _("             and version\n"));
    172 	fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
    173 	fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
    174 	fprintf( stderr, _("  -s scope   one of base, one, sub or children (search scope)\n"));
    175 	fprintf( stderr, _("  -S attr    sort the results by attribute `attr'\n"));
    176 	fprintf( stderr, _("  -t         write binary values to files in temporary directory\n"));
    177 	fprintf( stderr, _("  -tt        write all values to files in temporary directory\n"));
    178 	fprintf( stderr, _("  -T path    write files to directory specified by path (default: %s)\n"), def_tmpdir);
    179 	fprintf( stderr, _("  -u         include User Friendly entry names in the output\n"));
    180 	fprintf( stderr, _("  -z limit   size limit (in entries, or \"none\" or \"max\") for search\n"));
    181 	tool_common_usage();
    182 	exit( EXIT_FAILURE );
    183 }
    184 
    185 static void print_entry LDAP_P((
    186 	LDAP	*ld,
    187 	LDAPMessage	*entry,
    188 	int		attrsonly));
    189 
    190 static void print_reference(
    191 	LDAP *ld,
    192 	LDAPMessage *reference );
    193 
    194 static void print_extended(
    195 	LDAP *ld,
    196 	LDAPMessage *extended );
    197 
    198 static void print_syncinfo(
    199 	BerValue *info );
    200 
    201 static void print_partial(
    202 	LDAP *ld,
    203 	LDAPMessage *partial );
    204 
    205 static int print_result(
    206 	LDAP *ld,
    207 	LDAPMessage *result,
    208 	int search );
    209 
    210 static int dosearch LDAP_P((
    211 	LDAP	*ld,
    212 	char	*base,
    213 	int		scope,
    214 	char	*filtpatt,
    215 	char	*value,
    216 	char	**attrs,
    217 	int		attrsonly,
    218 	LDAPControl **sctrls,
    219 	LDAPControl **cctrls,
    220 	struct timeval *timeout,
    221 	int	sizelimit ));
    222 
    223 static char *tmpdir = NULL;
    224 static char *urlpre = NULL;
    225 static char	*base = NULL;
    226 static char	*sortattr = NULL;
    227 static int  includeufn, vals2tmp = 0;
    228 
    229 static int subentries = 0, valuesReturnFilter = 0;
    230 static char	*vrFilter = NULL;
    231 
    232 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
    233 static int accountUsability = 0;
    234 #endif
    235 
    236 #ifdef LDAP_CONTROL_DONTUSECOPY
    237 static int dontUseCopy = 0;
    238 #endif
    239 
    240 static int domainScope = 0;
    241 
    242 static int sss = 0;
    243 static LDAPSortKey **sss_keys = NULL;
    244 
    245 static int vlv = 0;
    246 static LDAPVLVInfo vlvInfo;
    247 static struct berval vlvValue;
    248 
    249 static int ldapsync = 0;
    250 static struct berval sync_cookie = { 0, NULL };
    251 static int sync_slimit = -1;
    252 
    253 static int psearch = 0;
    254 static int ps_chgtypes, ps_chgsonly, ps_echg_ctrls;
    255 
    256 /* cookie and morePagedResults moved to common.c */
    257 static int pagedResults = 0;
    258 static int pagePrompt = 1;
    259 static ber_int_t pageSize = 0;
    260 static ber_int_t entriesLeft = 0;
    261 static int npagedresponses;
    262 static int npagedentries;
    263 static int npagedreferences;
    264 static int npagedextended;
    265 static int npagedpartial;
    266 
    267 static LDAPControl *c = NULL;
    268 static int nctrls = 0;
    269 static int save_nctrls = 0;
    270 
    271 #ifdef LDAP_CONTROL_X_DEREF
    272 static int derefcrit;
    273 static LDAPDerefSpec *ds;
    274 static struct berval derefval;
    275 #endif
    276 
    277 #ifdef LDAP_CONTROL_X_DIRSYNC
    278 static int dirSync;
    279 static int dirSyncFlags;
    280 static int dirSyncMaxAttrCount;
    281 static struct berval dirSyncCookie;
    282 #endif
    283 
    284 #ifdef LDAP_CONTROL_X_EXTENDED_DN
    285 static int extendedDn;
    286 static int extendedDnFlag;
    287 #endif
    288 
    289 #ifdef LDAP_CONTROL_X_SHOW_DELETED
    290 static int showDeleted;
    291 #endif
    292 
    293 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
    294 static int serverNotif;
    295 #endif
    296 
    297 static int
    298 ctrl_add( void )
    299 {
    300 	LDAPControl	*tmpc;
    301 
    302 	nctrls++;
    303 	tmpc = realloc( c, sizeof( LDAPControl ) * nctrls );
    304 	if ( tmpc == NULL ) {
    305 		nctrls--;
    306 		fprintf( stderr,
    307 			_("unable to make room for control; out of memory?\n"));
    308 		return -1;
    309 	}
    310 	c = tmpc;
    311 
    312 	return 0;
    313 }
    314 
    315 static void
    316 urlize(char *url)
    317 {
    318 	char *p;
    319 
    320 	if (*LDAP_DIRSEP != '/') {
    321 		for (p = url; *p; p++) {
    322 			if (*p == *LDAP_DIRSEP)
    323 				*p = '/';
    324 		}
    325 	}
    326 }
    327 
    328 static int
    329 parse_vlv(char *cvalue)
    330 {
    331 	char *keyp, *key2;
    332 	int num1, num2;
    333 
    334 	keyp = cvalue;
    335 	if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
    336 		fprintf( stderr,
    337 			_("VLV control value \"%s\" invalid\n"),
    338 			cvalue );
    339 		return -1;
    340 	}
    341 	vlvInfo.ldvlv_before_count = num1;
    342 	vlvInfo.ldvlv_after_count = num2;
    343 	keyp = strchr( keyp, '/' ) + 1;
    344 	key2 = strchr( keyp, '/' );
    345 	if ( key2 ) {
    346 		keyp = key2 + 1;
    347 		if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
    348 			fprintf( stderr,
    349 				_("VLV control value \"%s\" invalid\n"),
    350 				cvalue );
    351 			return -1;
    352 		}
    353 		vlvInfo.ldvlv_offset = num1;
    354 		vlvInfo.ldvlv_count = num2;
    355 		vlvInfo.ldvlv_attrvalue = NULL;
    356 	} else {
    357 		key2 = strchr( keyp, ':' );
    358 		if ( !key2 ) {
    359 			fprintf( stderr,
    360 				_("VLV control value \"%s\" invalid\n"),
    361 				cvalue );
    362 			return -1;
    363 		}
    364 		ber_str2bv( key2+1, 0, 0, &vlvValue );
    365 		vlvInfo.ldvlv_attrvalue = &vlvValue;
    366 	}
    367 	return 0;
    368 }
    369 
    370 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
    371 	"Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
    372 
    373 int
    374 handle_private_option( int i )
    375 {
    376 	int crit, ival;
    377 	char *cvalue, *next;
    378 	switch ( i ) {
    379 	case 'a':	/* set alias deref option */
    380 		if ( strcasecmp( optarg, "never" ) == 0 ) {
    381 			deref = LDAP_DEREF_NEVER;
    382 		} else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
    383 			deref = LDAP_DEREF_SEARCHING;
    384 		} else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
    385 			deref = LDAP_DEREF_FINDING;
    386 		} else if ( strcasecmp( optarg, "always" ) == 0 ) {
    387 			deref = LDAP_DEREF_ALWAYS;
    388 		} else {
    389 			fprintf( stderr,
    390 				_("alias deref should be never, search, find, or always\n") );
    391 			usage();
    392 		}
    393 		break;
    394 	case 'A':	/* retrieve attribute names only -- no values */
    395 		++attrsonly;
    396 		break;
    397 	case 'b': /* search base */
    398 		base = optarg;
    399 		break;
    400 	case 'E': /* search extensions */
    401 		if( protocol == LDAP_VERSION2 ) {
    402 			fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
    403 				prog, protocol );
    404 			exit( EXIT_FAILURE );
    405 		}
    406 
    407 		/* should be extended to support comma separated list of
    408 		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
    409 		 */
    410 
    411 		crit = 0;
    412 		cvalue = NULL;
    413 		while ( optarg[0] == '!' ) {
    414 			crit++;
    415 			optarg++;
    416 		}
    417 
    418 		control = optarg;
    419 		if ( (cvalue = strchr( control, '=' )) != NULL ) {
    420 			*cvalue++ = '\0';
    421 		}
    422 
    423 		if ( strcasecmp( control, "mv" ) == 0 ) {
    424 			/* ValuesReturnFilter control */
    425 			if( valuesReturnFilter ) {
    426 				fprintf( stderr,
    427 					_("ValuesReturnFilter previously specified\n"));
    428 				exit( EXIT_FAILURE );
    429 			}
    430 			valuesReturnFilter= 1 + crit;
    431 
    432 			if ( cvalue == NULL ) {
    433 				fprintf( stderr,
    434 					_("missing filter in ValuesReturnFilter control\n"));
    435 				exit( EXIT_FAILURE );
    436 			}
    437 
    438 			vrFilter = cvalue;
    439 			protocol = LDAP_VERSION3;
    440 
    441 		} else if ( strcasecmp( control, "pr" ) == 0 ) {
    442 			int num, tmp;
    443 			/* PagedResults control */
    444 			if ( pagedResults != 0 ) {
    445 				fprintf( stderr,
    446 					_("PagedResultsControl previously specified\n") );
    447 				exit( EXIT_FAILURE );
    448 			}
    449 			if ( vlv != 0 ) {
    450 				fprintf( stderr,
    451 					_("PagedResultsControl incompatible with VLV\n") );
    452 				exit( EXIT_FAILURE );
    453 			}
    454 
    455 			if( cvalue != NULL ) {
    456 				char *promptp;
    457 
    458 				promptp = strchr( cvalue, '/' );
    459 				if ( promptp != NULL ) {
    460 					*promptp++ = '\0';
    461 					if ( strcasecmp( promptp, "prompt" ) == 0 ) {
    462 						pagePrompt = 1;
    463 					} else if ( strcasecmp( promptp, "noprompt" ) == 0) {
    464 						pagePrompt = 0;
    465 					} else {
    466 						fprintf( stderr,
    467 							_("Invalid value for PagedResultsControl,"
    468 							" %s/%s.\n"), cvalue, promptp );
    469 						exit( EXIT_FAILURE );
    470 					}
    471 				}
    472 				num = sscanf( cvalue, "%d", &tmp );
    473 				if ( num != 1 ) {
    474 					fprintf( stderr,
    475 						_("Invalid value for PagedResultsControl, %s.\n"),
    476 						cvalue );
    477 					exit( EXIT_FAILURE );
    478 				}
    479 			} else {
    480 				fprintf(stderr, _("Invalid value for PagedResultsControl.\n"));
    481 				exit( EXIT_FAILURE );
    482 			}
    483 			pageSize = (ber_int_t) tmp;
    484 			pagedResults = 1 + crit;
    485 
    486 		} else if ( strcasecmp( control, "ps" ) == 0 ) {
    487 			int num;
    488 			/* PersistentSearch control */
    489 			if ( psearch != 0 ) {
    490 				fprintf( stderr,
    491 					_("PersistentSearch previously specified\n") );
    492 				exit( EXIT_FAILURE );
    493 			}
    494 			if( cvalue != NULL ) {
    495 				num = sscanf( cvalue, "%i/%d/%d", &ps_chgtypes, &ps_chgsonly, &ps_echg_ctrls );
    496 				if ( num != 3 ) {
    497 					fprintf( stderr,
    498 						_("Invalid value for PersistentSearch, %s.\n"),
    499 						cvalue );
    500 					exit( EXIT_FAILURE );
    501 				}
    502 			} else {
    503 				fprintf(stderr, _("Invalid value for PersistentSearch.\n"));
    504 				exit( EXIT_FAILURE );
    505 			}
    506 			psearch = 1 + crit;
    507 
    508 #ifdef LDAP_CONTROL_DONTUSECOPY
    509 		} else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
    510 			if( dontUseCopy ) {
    511 				fprintf( stderr,
    512 					_("dontUseCopy control previously specified\n"));
    513 				exit( EXIT_FAILURE );
    514 			}
    515 			if( cvalue != NULL ) {
    516 				fprintf( stderr,
    517 			         _("dontUseCopy: no control value expected\n") );
    518 				usage();
    519 			}
    520 			if( !crit ) {
    521 				fprintf( stderr,
    522 			         _("dontUseCopy: critical flag required\n") );
    523 				usage();
    524 			}
    525 
    526 			dontUseCopy = 1 + crit;
    527 #endif
    528 		} else if ( strcasecmp( control, "domainScope" ) == 0 ) {
    529 			if( domainScope ) {
    530 				fprintf( stderr,
    531 					_("domainScope control previously specified\n"));
    532 				exit( EXIT_FAILURE );
    533 			}
    534 			if( cvalue != NULL ) {
    535 				fprintf( stderr,
    536 			         _("domainScope: no control value expected\n") );
    537 				usage();
    538 			}
    539 
    540 			domainScope = 1 + crit;
    541 
    542 		} else if ( strcasecmp( control, "sss" ) == 0 ) {
    543 			char *keyp;
    544 			if( sss ) {
    545 				fprintf( stderr,
    546 					_("server side sorting control previously specified\n"));
    547 				exit( EXIT_FAILURE );
    548 			}
    549 			if( cvalue == NULL ) {
    550 				fprintf( stderr,
    551 			         _("missing specification of sss control\n") );
    552 				exit( EXIT_FAILURE );
    553 			}
    554 			keyp = cvalue;
    555 			while ( ( keyp = strchr(keyp, '/') ) != NULL ) {
    556 				*keyp++ = ' ';
    557 			}
    558 			if ( ldap_create_sort_keylist( &sss_keys, cvalue )) {
    559 				fprintf( stderr,
    560 					_("server side sorting control value \"%s\" invalid\n"),
    561 					cvalue );
    562 				exit( EXIT_FAILURE );
    563 			}
    564 
    565 			sss = 1 + crit;
    566 
    567 		} else if ( strcasecmp( control, "subentries" ) == 0 ) {
    568 			if( subentries ) {
    569 				fprintf( stderr,
    570 					_("subentries control previously specified\n"));
    571 				exit( EXIT_FAILURE );
    572 			}
    573 			if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) {
    574 				subentries = 2;
    575 			} else if ( strcasecmp( cvalue, "false") == 0 ) {
    576 				subentries = 1;
    577 			} else {
    578 				fprintf( stderr,
    579 					_("subentries control value \"%s\" invalid\n"),
    580 					cvalue );
    581 				exit( EXIT_FAILURE );
    582 			}
    583 			if( crit ) subentries *= -1;
    584 
    585 		} else if ( strcasecmp( control, "sync" ) == 0 ) {
    586 			char *cookiep;
    587 			char *slimitp;
    588 			if ( ldapsync ) {
    589 				fprintf( stderr, _("sync control previously specified\n") );
    590 				exit( EXIT_FAILURE );
    591 			}
    592 			if ( cvalue == NULL ) {
    593 				fprintf( stderr, _("missing specification of sync control\n"));
    594 				exit( EXIT_FAILURE );
    595 			}
    596 			if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
    597 				ldapsync = LDAP_SYNC_REFRESH_ONLY;
    598 				cookiep = strchr( cvalue, '/' );
    599 				if ( cookiep != NULL ) {
    600 					cookiep++;
    601 					if ( *cookiep != '\0' ) {
    602 						ber_str2bv( cookiep, 0, 0, &sync_cookie );
    603 					}
    604 				}
    605 			} else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
    606 				ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
    607 				cookiep = strchr( cvalue, '/' );
    608 				if ( cookiep != NULL ) {
    609 					*cookiep++ = '\0';
    610 					cvalue = cookiep;
    611 				}
    612 				slimitp = strchr( cvalue, '/' );
    613 				if ( slimitp != NULL ) {
    614 					*slimitp++ = '\0';
    615 				}
    616 				if ( cookiep != NULL && *cookiep != '\0' )
    617 					ber_str2bv( cookiep, 0, 0, &sync_cookie );
    618 				if ( slimitp != NULL && *slimitp != '\0' ) {
    619 					ival = strtol( slimitp, &next, 10 );
    620 					if ( next == NULL || next[0] != '\0' ) {
    621 						fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp );
    622 						exit( EXIT_FAILURE );
    623 					}
    624 					sync_slimit = ival;
    625 				}
    626 			} else {
    627 				fprintf( stderr, _("sync control value \"%s\" invalid\n"),
    628 					cvalue );
    629 				exit( EXIT_FAILURE );
    630 			}
    631 			if ( crit ) ldapsync *= -1;
    632 
    633 		} else if ( strcasecmp( control, "vlv" ) == 0 ) {
    634 			if( vlv ) {
    635 				fprintf( stderr,
    636 					_("virtual list view control previously specified\n"));
    637 				exit( EXIT_FAILURE );
    638 			}
    639 			if ( pagedResults != 0 ) {
    640 				fprintf( stderr,
    641 					_("PagedResultsControl incompatible with VLV\n") );
    642 				exit( EXIT_FAILURE );
    643 			}
    644 			if( cvalue == NULL ) {
    645 				fprintf( stderr,
    646 			         _("missing specification of vlv control\n") );
    647 				exit( EXIT_FAILURE );
    648 			}
    649 			if ( parse_vlv( cvalue ))
    650 				exit( EXIT_FAILURE );
    651 
    652 			vlv = 1 + crit;
    653 
    654 #ifdef LDAP_CONTROL_X_DEREF
    655 		} else if ( strcasecmp( control, "deref" ) == 0 ) {
    656 			int ispecs;
    657 			char **specs;
    658 
    659 			/* cvalue is something like
    660 			 *
    661 			 * derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]"
    662 			 */
    663 
    664 			specs = ldap_str2charray( cvalue, ";" );
    665 			if ( specs == NULL ) {
    666 				fprintf( stderr, _("deref specs \"%s\" invalid\n"),
    667 					cvalue );
    668 				exit( EXIT_FAILURE );
    669 			}
    670 			for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
    671 				/* count'em */ ;
    672 
    673 			ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
    674 			if ( ds == NULL ) {
    675 				perror( "malloc" );
    676 				exit( EXIT_FAILURE );
    677 			}
    678 
    679 			for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
    680 				char *ptr;
    681 
    682 				ptr = strchr( specs[ ispecs ], ':' );
    683 				if ( ptr == NULL ) {
    684 					fprintf( stderr, _("deref specs \"%s\" invalid\n"),
    685 						cvalue );
    686 					exit( EXIT_FAILURE );
    687 				}
    688 
    689 				ds[ ispecs ].derefAttr = specs[ ispecs ];
    690 				*ptr++ = '\0';
    691 				ds[ ispecs ].attributes = ldap_str2charray( ptr, "," );
    692 			}
    693 
    694 			derefcrit = 1 + crit;
    695 
    696 			ldap_memfree( specs );
    697 #endif /* LDAP_CONTROL_X_DEREF */
    698 
    699 #ifdef LDAP_CONTROL_X_DIRSYNC
    700 		} else if ( strcasecmp( control, "dirSync" ) == 0 ) {
    701 			char *maxattrp;
    702 			char *cookiep;
    703 			int num, tmp;
    704 			if( dirSync ) {
    705 				fprintf( stderr,
    706 					_("dirSync control previously specified\n"));
    707 				exit( EXIT_FAILURE );
    708 			}
    709 			if ( cvalue == NULL ) {
    710 				fprintf( stderr, _("missing specification of dirSync control\n"));
    711 				exit( EXIT_FAILURE );
    712 			}
    713 			if( !crit ) {
    714 				fprintf( stderr,
    715 			         _("dirSync: critical flag required\n") );
    716 				usage();
    717 			}
    718 			maxattrp = strchr( cvalue, '/' );
    719 			if ( maxattrp == NULL ) {
    720 				fprintf( stderr, _("dirSync control value \"%s\" invalid\n"),
    721 					cvalue );
    722 				exit( EXIT_FAILURE );
    723 			}
    724 			*maxattrp++ = '\0';
    725 			cookiep = strchr( maxattrp, '/' );
    726 			if ( cookiep != NULL ) {
    727 				if ( cookiep[1] != '\0' ) {
    728 					struct berval type;
    729 					int freeval;
    730 					char save1, save2;
    731 
    732 					/* dummy type "x"
    733 					 * to use ldif_parse_line2() */
    734 					save1 = cookiep[ -1 ];
    735 					save2 = cookiep[ -2 ];
    736 					cookiep[ -2 ] = 'x';
    737 					cookiep[ -1 ] = ':';
    738 					cookiep[  0 ] = ':';
    739 					ldif_parse_line2( &cookiep[ -2 ], &type,
    740 						&dirSyncCookie, &freeval );
    741 					cookiep[ -1 ] = save1;
    742 					cookiep[ -2 ] = save2;
    743 				}
    744 				*cookiep = '\0';
    745 			}
    746 			num = sscanf( cvalue, "%i", &tmp );
    747 			if ( num != 1 ) {
    748 				fprintf( stderr,
    749 					_("Invalid value for dirSync, %s.\n"),
    750 					cvalue );
    751 				exit( EXIT_FAILURE );
    752 			}
    753 			dirSyncFlags = tmp;
    754 
    755 			num = sscanf( maxattrp, "%d", &tmp );
    756 			if ( num != 1 ) {
    757 				fprintf( stderr,
    758 					_("Invalid value for dirSync, %s.\n"),
    759 					maxattrp );
    760 				exit( EXIT_FAILURE );
    761 			}
    762 			dirSyncMaxAttrCount = tmp;
    763 
    764 			dirSync = 1 + crit;
    765 #endif /* LDAP_CONTROL_X_DIRSYNC */
    766 
    767 #ifdef LDAP_CONTROL_X_EXTENDED_DN
    768 		} else if ( strcasecmp( control, "extendedDn" ) == 0 ) {
    769 			int num, tmp;
    770 			if( extendedDn ) {
    771 				fprintf( stderr,
    772 					_("extendedDn control previously specified\n"));
    773 				exit( EXIT_FAILURE );
    774 			}
    775 			if ( cvalue == NULL ) {
    776 				fprintf( stderr, _("missing specification of extendedDn control\n"));
    777 				exit( EXIT_FAILURE );
    778 			}
    779 			num = sscanf( cvalue, "%d", &tmp );
    780 			if ( num != 1 ) {
    781 				fprintf( stderr,
    782 					_("Invalid value for extendedDn, %s.\n"),
    783 					cvalue );
    784 				exit( EXIT_FAILURE );
    785 			}
    786 
    787 			extendedDnFlag = tmp;
    788 			extendedDn = 1 + crit;
    789 #endif /* LDAP_CONTROL_X_EXTENDED_DN */
    790 
    791 #ifdef LDAP_CONTROL_X_SHOW_DELETED
    792 		} else if ( strcasecmp( control, "showDeleted" ) == 0 ) {
    793 			if( showDeleted ) {
    794 				fprintf( stderr,
    795 					_("showDeleted control previously specified\n"));
    796 				exit( EXIT_FAILURE );
    797 			}
    798 			if ( cvalue != NULL ) {
    799 				fprintf( stderr,
    800 			         _("showDeleted: no control value expected\n") );
    801 				usage();
    802 			}
    803 
    804 			showDeleted = 1 + crit;
    805 #endif /* LDAP_CONTROL_X_SHOW_DELETED */
    806 
    807 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
    808 		} else if ( strcasecmp( control, "serverNotif" ) == 0 ) {
    809 			if( serverNotif ) {
    810 				fprintf( stderr,
    811 					_("serverNotif control previously specified\n"));
    812 				exit( EXIT_FAILURE );
    813 			}
    814 			if ( cvalue != NULL ) {
    815 				fprintf( stderr,
    816 			         _("serverNotif: no control value expected\n") );
    817 				usage();
    818 			}
    819 
    820 			serverNotif = 1 + crit;
    821 #endif /* LDAP_CONTROL_X_SERVER_NOTIFICATION */
    822 
    823 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
    824 		} else if ( strcasecmp( control, "accountUsability" ) == 0 ) {
    825 			if( accountUsability ) {
    826 				fprintf( stderr,
    827 					_("accountUsability control previously specified\n"));
    828 				exit( EXIT_FAILURE );
    829 			}
    830 			if( cvalue != NULL ) {
    831 				fprintf( stderr,
    832 			         _("accountUsability: no control value expected\n") );
    833 				usage();
    834 			}
    835 
    836 			accountUsability = 1 + crit;
    837 #endif /* LDAP_CONTROL_X_ACCOUNT_USABILITY */
    838 
    839 		} else if ( tool_is_oid( control ) ) {
    840 			if ( c != NULL ) {
    841 				int i;
    842 				for ( i = 0; i < nctrls; i++ ) {
    843 					if ( strcmp( control, c[ i ].ldctl_oid ) == 0 ) {
    844 						fprintf( stderr, "%s control previously specified\n", control );
    845 						exit( EXIT_FAILURE );
    846 					}
    847 				}
    848 			}
    849 
    850 			if ( ctrl_add() ) {
    851 				exit( EXIT_FAILURE );
    852 			}
    853 
    854 			/* OID */
    855 			c[ nctrls - 1 ].ldctl_oid = control;
    856 
    857 			/* value */
    858 			if ( cvalue == NULL ) {
    859 				c[ nctrls - 1 ].ldctl_value.bv_val = NULL;
    860 				c[ nctrls - 1 ].ldctl_value.bv_len = 0;
    861 
    862 			} else if ( cvalue[ 0 ] == ':' ) {
    863 				struct berval type;
    864 				struct berval value;
    865 				int freeval;
    866 				char save_c;
    867 
    868 				cvalue++;
    869 
    870 				/* dummy type "x"
    871 				 * to use ldif_parse_line2() */
    872 				save_c = cvalue[ -2 ];
    873 				cvalue[ -2 ] = 'x';
    874 				ldif_parse_line2( &cvalue[ -2 ], &type,
    875 					&value, &freeval );
    876 				cvalue[ -2 ] = save_c;
    877 
    878 				if ( freeval ) {
    879 					c[ nctrls - 1 ].ldctl_value = value;
    880 
    881 				} else {
    882 					ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value );
    883 				}
    884 
    885 			} else {
    886 				fprintf( stderr, "unable to parse %s control value\n", control );
    887 				exit( EXIT_FAILURE );
    888 
    889 			}
    890 
    891 			/* criticality */
    892 			c[ nctrls - 1 ].ldctl_iscritical = crit;
    893 
    894 		} else {
    895 			fprintf( stderr, _("Invalid search extension name: %s\n"),
    896 				control );
    897 			usage();
    898 		}
    899 		break;
    900 	case 'F':	/* uri prefix */
    901 		if( urlpre ) free( urlpre );
    902 		urlpre = optarg;
    903 		break;
    904 	case 'l':	/* time limit */
    905 		if ( strcasecmp( optarg, "none" ) == 0 ) {
    906 			timelimit = 0;
    907 
    908 		} else if ( strcasecmp( optarg, "max" ) == 0 ) {
    909 			timelimit = LDAP_MAXINT;
    910 
    911 		} else {
    912 			ival = strtol( optarg, &next, 10 );
    913 			if ( next == NULL || next[0] != '\0' ) {
    914 				fprintf( stderr,
    915 					_("Unable to parse time limit \"%s\"\n"), optarg );
    916 				exit( EXIT_FAILURE );
    917 			}
    918 			timelimit = ival;
    919 		}
    920 		if( timelimit < 0 || timelimit > LDAP_MAXINT ) {
    921 			fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"),
    922 				prog, timelimit );
    923 			exit( EXIT_FAILURE );
    924 		}
    925 		break;
    926 	case 'L':	/* print entries in LDIF format */
    927 		++ldif;
    928 		break;
    929 	case 's':	/* search scope */
    930 		if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) {
    931 			scope = LDAP_SCOPE_BASE;
    932 		} else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) {
    933 			scope = LDAP_SCOPE_ONELEVEL;
    934 		} else if (( strcasecmp( optarg, "subordinate" ) == 0 )
    935 			|| ( strcasecmp( optarg, "children" ) == 0 ))
    936 		{
    937 			scope = LDAP_SCOPE_SUBORDINATE;
    938 		} else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) {
    939 			scope = LDAP_SCOPE_SUBTREE;
    940 		} else {
    941 			fprintf( stderr, _("scope should be base, one, or sub\n") );
    942 			usage();
    943 		}
    944 		break;
    945 	case 'S':	/* sort attribute */
    946 		sortattr = optarg;
    947 		break;
    948 	case 't':	/* write attribute values to TMPDIR files */
    949 		++vals2tmp;
    950 		break;
    951 	case 'T':	/* tmpdir */
    952 		if( tmpdir ) free( tmpdir );
    953 		tmpdir = optarg;
    954 		break;
    955 	case 'u':	/* include UFN */
    956 		++includeufn;
    957 		break;
    958 	case 'z':	/* size limit */
    959 		if ( strcasecmp( optarg, "none" ) == 0 ) {
    960 			sizelimit = 0;
    961 
    962 		} else if ( strcasecmp( optarg, "max" ) == 0 ) {
    963 			sizelimit = LDAP_MAXINT;
    964 
    965 		} else {
    966 			ival = strtol( optarg, &next, 10 );
    967 			if ( next == NULL || next[0] != '\0' ) {
    968 				fprintf( stderr,
    969 					_("Unable to parse size limit \"%s\"\n"), optarg );
    970 				exit( EXIT_FAILURE );
    971 			}
    972 			sizelimit = ival;
    973 		}
    974 		if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) {
    975 			fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"),
    976 				prog, sizelimit );
    977 			exit( EXIT_FAILURE );
    978 		}
    979 		break;
    980 	default:
    981 		return 0;
    982 	}
    983 	return 1;
    984 }
    985 
    986 
    987 static void
    988 private_conn_setup( LDAP *ld )
    989 {
    990 	if (deref != -1 &&
    991 		ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref )
    992 			!= LDAP_OPT_SUCCESS )
    993 	{
    994 		fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref );
    995 		tool_exit( ld, EXIT_FAILURE );
    996 	}
    997 }
    998 
    999 int
   1000 main( int argc, char **argv )
   1001 {
   1002 	char		*filtpattern, **attrs = NULL, line[BUFSIZ];
   1003 	FILE		*fp = NULL;
   1004 	int			rc, rc1, i, first;
   1005 	LDAP		*ld = NULL;
   1006 	BerElement	*seber = NULL, *vrber = NULL;
   1007 
   1008 	BerElement      *syncber = NULL;
   1009 	struct berval   *syncbvalp = NULL;
   1010 	int		err;
   1011 
   1012 	tool_init( TOOL_SEARCH );
   1013 
   1014 	npagedresponses = npagedentries = npagedreferences =
   1015 		npagedextended = npagedpartial = 0;
   1016 
   1017 	prog = lutil_progname( "ldapsearch", argc, argv );
   1018 
   1019 	if((def_tmpdir = getenv("TMPDIR")) == NULL &&
   1020 	   (def_tmpdir = getenv("TMP")) == NULL &&
   1021 	   (def_tmpdir = getenv("TEMP")) == NULL )
   1022 	{
   1023 		def_tmpdir = LDAP_TMPDIR;
   1024 	}
   1025 
   1026 	if ( !*def_tmpdir )
   1027 		def_tmpdir = LDAP_TMPDIR;
   1028 
   1029 	def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
   1030 
   1031 	if( def_urlpre == NULL ) {
   1032 		perror( "malloc" );
   1033 		return EXIT_FAILURE;
   1034 	}
   1035 
   1036 	sprintf( def_urlpre, "file:///%s/",
   1037 		def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
   1038 
   1039 	urlize( def_urlpre );
   1040 
   1041 	tool_args( argc, argv );
   1042 
   1043 	if ( vlv && !sss ) {
   1044 		fprintf( stderr,
   1045 			_("VLV control requires server side sort control\n" ));
   1046 		return EXIT_FAILURE;
   1047 	}
   1048 
   1049 	if (( argc - optind < 1 ) ||
   1050 		( *argv[optind] != '(' /*')'*/ &&
   1051 		( strchr( argv[optind], '=' ) == NULL ) ) )
   1052 	{
   1053 		filtpattern = "(objectclass=*)";
   1054 	} else {
   1055 		filtpattern = argv[optind++];
   1056 	}
   1057 
   1058 	if ( argv[optind] != NULL ) {
   1059 		attrs = &argv[optind];
   1060 	}
   1061 
   1062 	if ( infile != NULL ) {
   1063 		int percent = 0;
   1064 
   1065 		if ( infile[0] == '-' && infile[1] == '\0' ) {
   1066 			fp = stdin;
   1067 		} else if (( fp = fopen( infile, "r" )) == NULL ) {
   1068 			perror( infile );
   1069 			return EXIT_FAILURE;
   1070 		}
   1071 
   1072 		for( i=0 ; filtpattern[i] ; i++ ) {
   1073 			if( filtpattern[i] == '%' ) {
   1074 				if( percent ) {
   1075 					fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
   1076 						filtpattern );
   1077 					return EXIT_FAILURE;
   1078 				}
   1079 
   1080 				percent++;
   1081 
   1082 				if( filtpattern[i+1] != 's' ) {
   1083 					fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
   1084 						filtpattern );
   1085 					return EXIT_FAILURE;
   1086 				}
   1087 			}
   1088 		}
   1089 	}
   1090 
   1091 	if ( tmpdir == NULL ) {
   1092 		tmpdir = def_tmpdir;
   1093 
   1094 		if ( urlpre == NULL )
   1095 			urlpre = def_urlpre;
   1096 	}
   1097 
   1098 	if( urlpre == NULL ) {
   1099 		urlpre = malloc( sizeof("file:////") + strlen(tmpdir) );
   1100 
   1101 		if( urlpre == NULL ) {
   1102 			perror( "malloc" );
   1103 			return EXIT_FAILURE;
   1104 		}
   1105 
   1106 		sprintf( urlpre, "file:///%s/",
   1107 			tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir );
   1108 
   1109 		urlize( urlpre );
   1110 	}
   1111 
   1112 	if ( debug )
   1113 		ldif_debug = debug;
   1114 
   1115 	ld = tool_conn_setup( 0, &private_conn_setup );
   1116 
   1117 	tool_bind( ld );
   1118 
   1119 getNextPage:
   1120 	/* fp may have been closed, need to reopen if code jumps
   1121 	 * back here to getNextPage.
   1122 	 */
   1123 	if ( !fp && infile ) {
   1124 		if (( fp = fopen( infile, "r" )) == NULL ) {
   1125 			perror( infile );
   1126 			tool_exit( ld, EXIT_FAILURE );
   1127 		}
   1128 	}
   1129 	save_nctrls = nctrls;
   1130 	i = nctrls;
   1131 	if ( nctrls > 0
   1132 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
   1133 		|| accountUsability
   1134 #endif
   1135 #ifdef LDAP_CONTROL_DONTUSECOPY
   1136 		|| dontUseCopy
   1137 #endif
   1138 #ifdef LDAP_CONTROL_X_DEREF
   1139 		|| derefcrit
   1140 #endif
   1141 #ifdef LDAP_CONTROL_X_DIRSYNC
   1142 		|| dirSync
   1143 #endif
   1144 #ifdef LDAP_CONTROL_X_EXTENDED_DN
   1145 		|| extendedDn
   1146 #endif
   1147 #ifdef LDAP_CONTROL_X_SHOW_DELETED
   1148 		|| showDeleted
   1149 #endif
   1150 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
   1151 		|| serverNotif
   1152 #endif
   1153 		|| domainScope
   1154 		|| pagedResults
   1155 		|| psearch
   1156 		|| ldapsync
   1157 		|| sss
   1158 		|| subentries
   1159 		|| valuesReturnFilter
   1160 		|| vlv )
   1161 	{
   1162 
   1163 #ifdef LDAP_CONTROL_X_ACCOUNT_USABILITY
   1164 		if ( accountUsability ) {
   1165 			if ( ctrl_add() ) {
   1166 				tool_exit( ld, EXIT_FAILURE );
   1167 			}
   1168 
   1169 			c[i].ldctl_oid = LDAP_CONTROL_X_ACCOUNT_USABILITY;
   1170 			c[i].ldctl_value.bv_val = NULL;
   1171 			c[i].ldctl_value.bv_len = 0;
   1172 			c[i].ldctl_iscritical = accountUsability == 2;
   1173 			i++;
   1174 		}
   1175 #endif
   1176 
   1177 #ifdef LDAP_CONTROL_DONTUSECOPY
   1178 		if ( dontUseCopy ) {
   1179 			if ( ctrl_add() ) {
   1180 				tool_exit( ld, EXIT_FAILURE );
   1181 			}
   1182 
   1183 			c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
   1184 			c[i].ldctl_value.bv_val = NULL;
   1185 			c[i].ldctl_value.bv_len = 0;
   1186 			c[i].ldctl_iscritical = dontUseCopy == 2;
   1187 			i++;
   1188 		}
   1189 #endif
   1190 
   1191 		if ( domainScope ) {
   1192 			if ( ctrl_add() ) {
   1193 				tool_exit( ld, EXIT_FAILURE );
   1194 			}
   1195 
   1196 			c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
   1197 			c[i].ldctl_value.bv_val = NULL;
   1198 			c[i].ldctl_value.bv_len = 0;
   1199 			c[i].ldctl_iscritical = domainScope > 1;
   1200 			i++;
   1201 		}
   1202 
   1203 		if ( subentries ) {
   1204 			if ( ctrl_add() ) {
   1205 				tool_exit( ld, EXIT_FAILURE );
   1206 			}
   1207 
   1208 			if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
   1209 				tool_exit( ld, EXIT_FAILURE );
   1210 			}
   1211 
   1212 			err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
   1213 			if ( err == -1 ) {
   1214 				ber_free( seber, 1 );
   1215 				fprintf( stderr, _("Subentries control encoding error!\n") );
   1216 				tool_exit( ld, EXIT_FAILURE );
   1217 			}
   1218 
   1219 			if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) {
   1220 				tool_exit( ld, EXIT_FAILURE );
   1221 			}
   1222 
   1223 			c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES;
   1224 			c[i].ldctl_iscritical = subentries < 1;
   1225 			i++;
   1226 		}
   1227 
   1228 		if ( ldapsync ) {
   1229 			if ( ctrl_add() ) {
   1230 				tool_exit( ld, EXIT_FAILURE );
   1231 			}
   1232 
   1233 			if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
   1234 				tool_exit( ld, EXIT_FAILURE );
   1235 			}
   1236 
   1237 			if ( sync_cookie.bv_len == 0 ) {
   1238 				err = ber_printf( syncber, "{e}", abs(ldapsync) );
   1239 			} else {
   1240 				err = ber_printf( syncber, "{eO}", abs(ldapsync),
   1241 							&sync_cookie );
   1242 			}
   1243 
   1244 			if ( err == -1 ) {
   1245 				ber_free( syncber, 1 );
   1246 				fprintf( stderr, _("ldap sync control encoding error!\n") );
   1247 				tool_exit( ld, EXIT_FAILURE );
   1248 			}
   1249 
   1250 			if ( ber_flatten( syncber, &syncbvalp ) == -1 ) {
   1251 				tool_exit( ld, EXIT_FAILURE );
   1252 			}
   1253 
   1254 			c[i].ldctl_oid = LDAP_CONTROL_SYNC;
   1255 			c[i].ldctl_value = (*syncbvalp);
   1256 			c[i].ldctl_iscritical = ldapsync < 0;
   1257 			i++;
   1258 		}
   1259 
   1260 		if ( valuesReturnFilter ) {
   1261 			if ( ctrl_add() ) {
   1262 				tool_exit( ld, EXIT_FAILURE );
   1263 			}
   1264 
   1265 			if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
   1266 				tool_exit( ld, EXIT_FAILURE );
   1267 			}
   1268 
   1269 			if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) {
   1270 				ber_free( vrber, 1 );
   1271 				fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter );
   1272 				tool_exit( ld, EXIT_FAILURE );
   1273 			}
   1274 
   1275 			if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) {
   1276 				tool_exit( ld, EXIT_FAILURE );
   1277 			}
   1278 
   1279 			c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
   1280 			c[i].ldctl_iscritical = valuesReturnFilter > 1;
   1281 			i++;
   1282 		}
   1283 
   1284 		if ( pagedResults ) {
   1285 			if ( ctrl_add() ) {
   1286 				tool_exit( ld, EXIT_FAILURE );
   1287 			}
   1288 
   1289 			if ( ldap_create_page_control_value( ld,
   1290 				pageSize, &pr_cookie, &c[i].ldctl_value ) )
   1291 			{
   1292 				tool_exit( ld, EXIT_FAILURE );
   1293 			}
   1294 
   1295 			if ( pr_cookie.bv_val != NULL ) {
   1296 				ber_memfree( pr_cookie.bv_val );
   1297 				pr_cookie.bv_val = NULL;
   1298 				pr_cookie.bv_len = 0;
   1299 			}
   1300 
   1301 			c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
   1302 			c[i].ldctl_iscritical = pagedResults > 1;
   1303 			i++;
   1304 		}
   1305 
   1306 		if ( psearch ) {
   1307 			if ( ctrl_add() ) {
   1308 				tool_exit( ld, EXIT_FAILURE );
   1309 			}
   1310 
   1311 			if ( ldap_create_persistentsearch_control_value( ld,
   1312 				ps_chgtypes, ps_chgsonly, ps_echg_ctrls, &c[i].ldctl_value ) )
   1313 			{
   1314 				tool_exit( ld, EXIT_FAILURE );
   1315 			}
   1316 
   1317 			c[i].ldctl_oid = LDAP_CONTROL_PERSIST_REQUEST;
   1318 			c[i].ldctl_iscritical = psearch > 1;
   1319 			i++;
   1320 		}
   1321 
   1322 		if ( sss ) {
   1323 			if ( ctrl_add() ) {
   1324 				tool_exit( ld, EXIT_FAILURE );
   1325 			}
   1326 
   1327 			if ( ldap_create_sort_control_value( ld,
   1328 				sss_keys, &c[i].ldctl_value ) )
   1329 			{
   1330 				tool_exit( ld, EXIT_FAILURE );
   1331 			}
   1332 
   1333 			c[i].ldctl_oid = LDAP_CONTROL_SORTREQUEST;
   1334 			c[i].ldctl_iscritical = sss > 1;
   1335 			i++;
   1336 		}
   1337 
   1338 		if ( vlv ) {
   1339 			if ( ctrl_add() ) {
   1340 				tool_exit( ld, EXIT_FAILURE );
   1341 			}
   1342 
   1343 			if ( ldap_create_vlv_control_value( ld,
   1344 				&vlvInfo, &c[i].ldctl_value ) )
   1345 			{
   1346 				tool_exit( ld, EXIT_FAILURE );
   1347 			}
   1348 
   1349 			c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
   1350 			c[i].ldctl_iscritical = vlv > 1;
   1351 			i++;
   1352 		}
   1353 #ifdef LDAP_CONTROL_X_DEREF
   1354 		if ( derefcrit ) {
   1355 			if ( derefval.bv_val == NULL ) {
   1356 				int i;
   1357 
   1358 				assert( ds != NULL );
   1359 
   1360 				if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
   1361 					tool_exit( ld, EXIT_FAILURE );
   1362 				}
   1363 
   1364 				for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) {
   1365 					ldap_memfree( ds[ i ].derefAttr );
   1366 					ldap_charray_free( ds[ i ].attributes );
   1367 				}
   1368 				ldap_memfree( ds );
   1369 				ds = NULL;
   1370 			}
   1371 
   1372 			if ( ctrl_add() ) {
   1373 				tool_exit( ld, EXIT_FAILURE );
   1374 			}
   1375 
   1376 			c[ i ].ldctl_iscritical = derefcrit > 1;
   1377 			c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF;
   1378 			c[ i ].ldctl_value = derefval;
   1379 			i++;
   1380 		}
   1381 #endif /* LDAP_CONTROL_X_DEREF */
   1382 #ifdef LDAP_CONTROL_X_DIRSYNC
   1383 		if ( dirSync ) {
   1384 			if ( ctrl_add() ) {
   1385 				tool_exit( ld, EXIT_FAILURE );
   1386 			}
   1387 
   1388 			if ( ldap_create_dirsync_value( ld,
   1389 				dirSyncFlags, dirSyncMaxAttrCount, &dirSyncCookie,
   1390 				&c[i].ldctl_value ) )
   1391 			{
   1392 				tool_exit( ld, EXIT_FAILURE );
   1393 			}
   1394 
   1395 			c[i].ldctl_oid = LDAP_CONTROL_X_DIRSYNC;
   1396 			c[i].ldctl_iscritical = dirSync > 1;
   1397 			i++;
   1398 		}
   1399 #endif
   1400 #ifdef LDAP_CONTROL_X_EXTENDED_DN
   1401 		if ( extendedDn ) {
   1402 			if ( ctrl_add() ) {
   1403 				tool_exit( ld, EXIT_FAILURE );
   1404 			}
   1405 
   1406 			if ( ldap_create_extended_dn_value( ld,
   1407 				extendedDnFlag, &c[i].ldctl_value ) )
   1408 			{
   1409 				tool_exit( ld, EXIT_FAILURE );
   1410 			}
   1411 
   1412 			c[i].ldctl_oid = LDAP_CONTROL_X_EXTENDED_DN;
   1413 			c[i].ldctl_iscritical = extendedDn > 1;
   1414 			i++;
   1415 		}
   1416 #endif
   1417 #ifdef LDAP_CONTROL_X_SHOW_DELETED
   1418 		if ( showDeleted ) {
   1419 			if ( ctrl_add() ) {
   1420 				tool_exit( ld, EXIT_FAILURE );
   1421 			}
   1422 
   1423 			c[i].ldctl_oid = LDAP_CONTROL_X_SHOW_DELETED;
   1424 			c[i].ldctl_value.bv_val = NULL;
   1425 			c[i].ldctl_value.bv_len = 0;
   1426 			c[i].ldctl_iscritical = showDeleted > 1;
   1427 			i++;
   1428 		}
   1429 #endif
   1430 #ifdef LDAP_CONTROL_X_SERVER_NOTIFICATION
   1431 		if ( serverNotif ) {
   1432 			if ( ctrl_add() ) {
   1433 				tool_exit( ld, EXIT_FAILURE );
   1434 			}
   1435 
   1436 			c[i].ldctl_oid = LDAP_CONTROL_X_SERVER_NOTIFICATION;
   1437 			c[i].ldctl_value.bv_val = NULL;
   1438 			c[i].ldctl_value.bv_len = 0;
   1439 			c[i].ldctl_iscritical = serverNotif > 1;
   1440 			i++;
   1441 		}
   1442 #endif
   1443 	}
   1444 
   1445 	tool_server_controls( ld, c, i );
   1446 
   1447 	if ( seber ) ber_free( seber, 1 );
   1448 	if ( vrber ) ber_free( vrber, 1 );
   1449 
   1450 	/* step back to the original number of controls, so that
   1451 	 * those set while parsing args are preserved */
   1452 	nctrls = save_nctrls;
   1453 
   1454 	if ( verbose ) {
   1455 		fprintf( stderr, _("filter%s: %s\nrequesting: "),
   1456 			infile != NULL ? _(" pattern") : "",
   1457 			filtpattern );
   1458 
   1459 		if ( attrs == NULL ) {
   1460 			fprintf( stderr, _("All userApplication attributes") );
   1461 		} else {
   1462 			for ( i = 0; attrs[ i ] != NULL; ++i ) {
   1463 				fprintf( stderr, "%s ", attrs[ i ] );
   1464 			}
   1465 		}
   1466 		fprintf( stderr, "\n" );
   1467 	}
   1468 
   1469 	if ( ldif == 0 ) {
   1470 		printf( _("# extended LDIF\n") );
   1471 	} else if ( ldif < 3 ) {
   1472 		printf( _("version: %d\n\n"), 1 );
   1473 	}
   1474 
   1475 	if (ldif < 2 ) {
   1476 		char	*realbase = base;
   1477 
   1478 		if ( realbase == NULL ) {
   1479 			ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase );
   1480 		}
   1481 
   1482 		printf( "#\n" );
   1483 		printf(_("# LDAPv%d\n"), protocol);
   1484 		printf(_("# base <%s>%s with scope %s\n"),
   1485 			realbase ? realbase : "",
   1486 			( realbase == NULL || realbase != base ) ? " (default)" : "",
   1487 			((scope == LDAP_SCOPE_BASE) ? "baseObject"
   1488 				: ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
   1489 				: ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
   1490 				: "subtree" ))));
   1491 		printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "",
   1492 		       filtpattern);
   1493 		printf(_("# requesting: "));
   1494 
   1495 		if ( attrs == NULL ) {
   1496 			printf( _("ALL") );
   1497 		} else {
   1498 			for ( i = 0; attrs[ i ] != NULL; ++i ) {
   1499 				printf( "%s ", attrs[ i ] );
   1500 			}
   1501 		}
   1502 
   1503 		if ( manageDSAit ) {
   1504 			printf(_("\n# with manageDSAit %scontrol"),
   1505 				manageDSAit > 1 ? _("critical ") : "" );
   1506 		}
   1507 		if ( noop ) {
   1508 			printf(_("\n# with noop %scontrol"),
   1509 				noop > 1 ? _("critical ") : "" );
   1510 		}
   1511 		if ( subentries ) {
   1512 			printf(_("\n# with subentries %scontrol: %s"),
   1513 				subentries < 0 ? _("critical ") : "",
   1514 				abs(subentries) == 1 ? "false" : "true" );
   1515 		}
   1516 		if ( valuesReturnFilter ) {
   1517 			printf(_("\n# with valuesReturnFilter %scontrol: %s"),
   1518 				valuesReturnFilter > 1 ? _("critical ") : "", vrFilter );
   1519 		}
   1520 		if ( pagedResults ) {
   1521 			printf(_("\n# with pagedResults %scontrol: size=%d"),
   1522 				(pagedResults > 1) ? _("critical ") : "",
   1523 				pageSize );
   1524 		}
   1525 		if ( sss ) {
   1526 			printf(_("\n# with server side sorting %scontrol"),
   1527 				sss > 1 ? _("critical ") : "" );
   1528 		}
   1529 		if ( vlv ) {
   1530 			printf(_("\n# with virtual list view %scontrol: %d/%d"),
   1531 				vlv > 1 ? _("critical ") : "",
   1532 				vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count);
   1533 			if ( vlvInfo.ldvlv_attrvalue )
   1534 				printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val );
   1535 			else
   1536 				printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count );
   1537 		}
   1538 #ifdef LDAP_CONTROL_X_DEREF
   1539 		if ( derefcrit ) {
   1540 			printf(_("\n# with dereference %scontrol"),
   1541 				derefcrit > 1 ? _("critical ") : "" );
   1542 		}
   1543 #endif
   1544 
   1545 		printf( _("\n#\n\n") );
   1546 
   1547 		if ( realbase && realbase != base ) {
   1548 			ldap_memfree( realbase );
   1549 		}
   1550 	}
   1551 
   1552 	if ( infile == NULL ) {
   1553 		rc = dosearch( ld, base, scope, NULL, filtpattern,
   1554 			attrs, attrsonly, NULL, NULL, NULL, sizelimit );
   1555 
   1556 	} else {
   1557 		rc = 0;
   1558 		first = 1;
   1559 		while ( fgets( line, sizeof( line ), fp ) != NULL ) {
   1560 			line[ strlen( line ) - 1 ] = '\0';
   1561 			if ( !first ) {
   1562 				putchar( '\n' );
   1563 			} else {
   1564 				first = 0;
   1565 			}
   1566 			rc1 = dosearch( ld, base, scope, filtpattern, line,
   1567 				attrs, attrsonly, NULL, NULL, NULL, sizelimit );
   1568 
   1569 			if ( rc1 != 0 ) {
   1570 				rc = rc1;
   1571 				if ( !contoper )
   1572 					break;
   1573 			}
   1574 		}
   1575 		if ( fp != stdin ) {
   1576 			fclose( fp );
   1577 			fp = NULL;
   1578 		}
   1579 	}
   1580 
   1581 	if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) {
   1582 		char	buf[12];
   1583 		int	i, moreEntries, tmpSize;
   1584 
   1585 		/* Loop to get the next pages when
   1586 		 * enter is pressed on the terminal.
   1587 		 */
   1588 		if ( pagePrompt != 0 ) {
   1589 			if ( entriesLeft > 0 ) {
   1590 				printf( _("Estimate entries: %d\n"), entriesLeft );
   1591 			}
   1592 			printf( _("Press [size] Enter for the next {%d|size} entries.\n"),
   1593 				(int)pageSize );
   1594 			i = 0;
   1595 			moreEntries = getchar();
   1596 			while ( moreEntries != EOF && moreEntries != '\n' ) {
   1597 				if ( i < (int)sizeof(buf) - 1 ) {
   1598 					buf[i] = moreEntries;
   1599 					i++;
   1600 				}
   1601 				moreEntries = getchar();
   1602 			}
   1603 			buf[i] = '\0';
   1604 
   1605 			if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) {
   1606 				int num = sscanf( buf, "%d", &tmpSize );
   1607 				if ( num != 1 ) {
   1608 					fprintf( stderr,
   1609 						_("Invalid value for PagedResultsControl, %s.\n"), buf);
   1610 					tool_exit( ld, EXIT_FAILURE );
   1611 
   1612 				}
   1613 				pageSize = (ber_int_t)tmpSize;
   1614 			}
   1615 		}
   1616 
   1617 		goto getNextPage;
   1618 	}
   1619 
   1620 	if (( rc == LDAP_SUCCESS ) && vlv ) {
   1621 		char	buf[BUFSIZ];
   1622 		int	i, moreEntries;
   1623 
   1624 		/* Loop to get the next window when
   1625 		 * enter is pressed on the terminal.
   1626 		 */
   1627 		printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n"));
   1628 		i = 0;
   1629 		moreEntries = getchar();
   1630 		while ( moreEntries != EOF && moreEntries != '\n' ) {
   1631 			if ( i < (int)sizeof(buf) - 1 ) {
   1632 				buf[i] = moreEntries;
   1633 				i++;
   1634 			}
   1635 			moreEntries = getchar();
   1636 		}
   1637 		buf[i] = '\0';
   1638 		if ( buf[0] ) {
   1639 			i = parse_vlv( strdup( buf ));
   1640 			if ( i )
   1641 				tool_exit( ld, EXIT_FAILURE );
   1642 		} else {
   1643 			vlvInfo.ldvlv_attrvalue = NULL;
   1644 			vlvInfo.ldvlv_count = vlvCount;
   1645 			vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count;
   1646 		}
   1647 
   1648 		if ( vlvInfo.ldvlv_context )
   1649 			ber_bvfree( vlvInfo.ldvlv_context );
   1650 		vlvInfo.ldvlv_context = vlvContext;
   1651 
   1652 		goto getNextPage;
   1653 	}
   1654 
   1655 	if ( sss_keys != NULL ) {
   1656 		ldap_free_sort_keylist( sss_keys );
   1657 	}
   1658 	if ( derefval.bv_val != NULL ) {
   1659 		ldap_memfree( derefval.bv_val );
   1660 	}
   1661 	if ( urlpre != NULL ) {
   1662 		if ( def_urlpre != urlpre )
   1663 			free( def_urlpre );
   1664 		free( urlpre );
   1665 	}
   1666 
   1667 	if ( c ) {
   1668 		for ( ; save_nctrls-- > 0; ) {
   1669 			ber_memfree( c[ save_nctrls ].ldctl_value.bv_val );
   1670 		}
   1671 		free( c );
   1672 		c = NULL;
   1673 	}
   1674 
   1675 	tool_exit( ld, rc );
   1676 }
   1677 
   1678 
   1679 static int dosearch(
   1680 	LDAP	*ld,
   1681 	char	*base,
   1682 	int		scope,
   1683 	char	*filtpatt,
   1684 	char	*value,
   1685 	char	**attrs,
   1686 	int		attrsonly,
   1687 	LDAPControl **sctrls,
   1688 	LDAPControl **cctrls,
   1689 	struct timeval *timeout,
   1690 	int sizelimit )
   1691 {
   1692 	char			*filter;
   1693 	int			rc, rc2 = LDAP_OTHER;
   1694 	int			nresponses;
   1695 	int			nentries;
   1696 	int			nreferences;
   1697 	int			nextended;
   1698 	int			npartial;
   1699 	LDAPMessage		*res, *msg;
   1700 	ber_int_t		msgid;
   1701 	char			*retoid = NULL;
   1702 	struct berval		*retdata = NULL;
   1703 	int			nresponses_psearch = -1;
   1704 	int			cancel_msgid = -1;
   1705 	struct timeval tv, *tvp = NULL;
   1706 	struct timeval tv_timelimit, *tv_timelimitp = NULL;
   1707 
   1708 	if( filtpatt != NULL ) {
   1709 		size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1, outlen;
   1710 		filter = malloc( max_fsize );
   1711 		if( filter == NULL ) {
   1712 			perror( "malloc" );
   1713 			return EXIT_FAILURE;
   1714 		}
   1715 
   1716 		outlen = snprintf( filter, max_fsize, filtpatt, value );
   1717 		if( outlen >= max_fsize ) {
   1718 			fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt );
   1719 			free( filter );
   1720 			return EXIT_FAILURE;
   1721 		}
   1722 
   1723 		if ( verbose ) {
   1724 			fprintf( stderr, _("filter: %s\n"), filter );
   1725 		}
   1726 
   1727 		if( ldif < 2 ) {
   1728 			printf( _("#\n# filter: %s\n#\n"), filter );
   1729 		}
   1730 
   1731 	} else {
   1732 		filter = value;
   1733 	}
   1734 
   1735 	if ( dont ) {
   1736 		if ( filtpatt != NULL ) {
   1737 			free( filter );
   1738 		}
   1739 		return LDAP_SUCCESS;
   1740 	}
   1741 
   1742 	if ( timelimit > 0 ) {
   1743 		tv_timelimit.tv_sec = timelimit;
   1744 		tv_timelimit.tv_usec = 0;
   1745 		tv_timelimitp = &tv_timelimit;
   1746 	}
   1747 
   1748 again:
   1749 	rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
   1750 		sctrls, cctrls, tv_timelimitp, sizelimit, &msgid );
   1751 
   1752 	if ( filtpatt != NULL ) {
   1753 		free( filter );
   1754 	}
   1755 
   1756 	if( rc != LDAP_SUCCESS ) {
   1757 		tool_perror( "ldap_search_ext", rc, NULL, NULL, NULL, NULL );
   1758 		return( rc );
   1759 	}
   1760 
   1761 	nresponses = nentries = nreferences = nextended = npartial = 0;
   1762 
   1763 	res = NULL;
   1764 
   1765 	if ( timelimit > 0 ) {
   1766 		/* disable timeout */
   1767 		tv.tv_sec = -1;
   1768 		tv.tv_usec = 0;
   1769 		tvp = &tv;
   1770 	}
   1771 
   1772 	if ( backlog == 1 ) {
   1773 		printf( _("\nWaiting for responses to accumulate, press Enter to continue: "));
   1774 		fflush( stdout );
   1775 		getchar();
   1776 		printf( _("Abandoning msgid %d\n"), msgid );
   1777 		ldap_abandon_ext( ld, msgid, NULL, NULL );
   1778 		/* turn off syncrepl control */
   1779 		ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, NULL );
   1780 		backlog = 2;
   1781 		scope = LDAP_SCOPE_BASE;
   1782 		goto again;
   1783 	} else if ( backlog == 2 ) {
   1784 		tv.tv_sec = timelimit;
   1785 	}
   1786 
   1787 	while ((rc = ldap_result( ld, LDAP_RES_ANY,
   1788 		sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE,
   1789 		tvp, &res )) > 0 )
   1790 	{
   1791 		if ( tool_check_abandon( ld, msgid ) ) {
   1792 			return -1;
   1793 		}
   1794 
   1795 		if( sortattr ) {
   1796 			(void) ldap_sort_entries( ld, &res,
   1797 				( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
   1798 		}
   1799 
   1800 		for ( msg = ldap_first_message( ld, res );
   1801 			msg != NULL;
   1802 			msg = ldap_next_message( ld, msg ) )
   1803 		{
   1804 			if ( nresponses++ ) putchar('\n');
   1805 			if ( nresponses_psearch >= 0 )
   1806 				nresponses_psearch++;
   1807 
   1808 			switch( ldap_msgtype( msg ) ) {
   1809 			case LDAP_RES_SEARCH_ENTRY:
   1810 				nentries++;
   1811 				print_entry( ld, msg, attrsonly );
   1812 				break;
   1813 
   1814 			case LDAP_RES_SEARCH_REFERENCE:
   1815 				nreferences++;
   1816 				print_reference( ld, msg );
   1817 				break;
   1818 
   1819 			case LDAP_RES_EXTENDED:
   1820 				nextended++;
   1821 				print_extended( ld, msg );
   1822 
   1823 				if ( ldap_msgid( msg ) == 0 ) {
   1824 					/* unsolicited extended operation */
   1825 					goto done;
   1826 				}
   1827 
   1828 				if ( cancel_msgid != -1 &&
   1829 						cancel_msgid == ldap_msgid( msg ) ) {
   1830 					printf(_("Cancelled \n"));
   1831 					printf(_("cancel_msgid = %d\n"), cancel_msgid);
   1832 					goto done;
   1833 				}
   1834 				break;
   1835 
   1836 			case LDAP_RES_SEARCH_RESULT:
   1837 				/* pagedResults stuff is dealt with
   1838 				 * in tool_print_ctrls(), called by
   1839 				 * print_results(). */
   1840 				rc2 = print_result( ld, msg, 1 );
   1841 				if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
   1842 					break;
   1843 				}
   1844 
   1845 				goto done;
   1846 
   1847 			case LDAP_RES_INTERMEDIATE:
   1848 				npartial++;
   1849 				ldap_parse_intermediate( ld, msg,
   1850 					&retoid, &retdata, NULL, 0 );
   1851 
   1852 				nresponses_psearch = 0;
   1853 
   1854 				if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) {
   1855 					if ( ldif < 1 ) {
   1856 						print_syncinfo( retdata );
   1857 					} else if ( ldif < 2 ) {
   1858 						printf(_("# SyncInfo Received\n"));
   1859 					}
   1860 					ldap_memfree( retoid );
   1861 					ber_bvfree( retdata );
   1862 					break;
   1863 				}
   1864 
   1865 				print_partial( ld, msg );
   1866 				ldap_memfree( retoid );
   1867 				ber_bvfree( retdata );
   1868 				goto done;
   1869 			}
   1870 
   1871 			if ( ldapsync && sync_slimit != -1 &&
   1872 					nresponses_psearch >= sync_slimit ) {
   1873 				BerElement *msgidber = NULL;
   1874 				struct berval *msgidvalp = NULL;
   1875 				msgidber = ber_alloc_t(LBER_USE_DER);
   1876 				ber_printf(msgidber, "{i}", msgid);
   1877 				ber_flatten(msgidber, &msgidvalp);
   1878 				ldap_extended_operation(ld, LDAP_EXOP_CANCEL,
   1879 					msgidvalp, NULL, NULL, &cancel_msgid);
   1880 				nresponses_psearch = -1;
   1881 			}
   1882 		}
   1883 
   1884 		ldap_msgfree( res );
   1885 		fflush( stdout );
   1886 	}
   1887 
   1888 done:
   1889 	if ( tvp == NULL && rc != LDAP_RES_SEARCH_RESULT ) {
   1890 		ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&rc2 );
   1891 	}
   1892 
   1893 	ldap_msgfree( res );
   1894 
   1895 	if ( pagedResults ) {
   1896 		npagedresponses += nresponses;
   1897 		npagedentries += nentries;
   1898 		npagedextended += nextended;
   1899 		npagedpartial += npartial;
   1900 		npagedreferences += nreferences;
   1901 		if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) {
   1902 			printf( _("\n# numResponses: %d\n"), npagedresponses );
   1903 			if( npagedentries ) {
   1904 				printf( _("# numEntries: %d\n"), npagedentries );
   1905 			}
   1906 			if( npagedextended ) {
   1907 				printf( _("# numExtended: %d\n"), npagedextended );
   1908 			}
   1909 			if( npagedpartial ) {
   1910 				printf( _("# numPartial: %d\n"), npagedpartial );
   1911 			}
   1912 			if( npagedreferences ) {
   1913 				printf( _("# numReferences: %d\n"), npagedreferences );
   1914 			}
   1915 		}
   1916 	} else if ( ldif < 2 ) {
   1917 		printf( _("\n# numResponses: %d\n"), nresponses );
   1918 		if( nentries ) printf( _("# numEntries: %d\n"), nentries );
   1919 		if( nextended ) printf( _("# numExtended: %d\n"), nextended );
   1920 		if( npartial ) printf( _("# numPartial: %d\n"), npartial );
   1921 		if( nreferences ) printf( _("# numReferences: %d\n"), nreferences );
   1922 	}
   1923 
   1924 	if ( rc != LDAP_RES_SEARCH_RESULT ) {
   1925 		tool_perror( "ldap_result", rc2, NULL, NULL, NULL, NULL );
   1926 	}
   1927 
   1928 	return( rc2 );
   1929 }
   1930 
   1931 /* This is the proposed new way of doing things.
   1932  * It is more efficient, but the API is non-standard.
   1933  */
   1934 static void
   1935 print_entry(
   1936 	LDAP	*ld,
   1937 	LDAPMessage	*entry,
   1938 	int		attrsonly)
   1939 {
   1940 	char		*ufn = NULL;
   1941 	char	tmpfname[ 256 ];
   1942 	char	url[ 256 ];
   1943 	int			i, rc;
   1944 	BerElement		*ber = NULL;
   1945 	struct berval		bv, *bvals, **bvp = &bvals;
   1946 	LDAPControl **ctrls = NULL;
   1947 	FILE		*tmpfp;
   1948 
   1949 	rc = ldap_get_dn_ber( ld, entry, &ber, &bv );
   1950 
   1951 	if ( ldif < 2 ) {
   1952 		ufn = ldap_dn2ufn( bv.bv_val );
   1953 		tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 );
   1954 	}
   1955 	tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
   1956 
   1957 	rc = ldap_get_entry_controls( ld, entry, &ctrls );
   1958 	if( rc != LDAP_SUCCESS ) {
   1959 		fprintf(stderr, _("print_entry: %d\n"), rc );
   1960 		tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL );
   1961 		tool_exit( ld, EXIT_FAILURE );
   1962 	}
   1963 
   1964 	if( ctrls ) {
   1965 		tool_print_ctrls( ld, ctrls );
   1966 		ldap_controls_free( ctrls );
   1967 	}
   1968 
   1969 	if ( includeufn ) {
   1970 		if( ufn == NULL ) {
   1971 			ufn = ldap_dn2ufn( bv.bv_val );
   1972 		}
   1973 		tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 );
   1974 	}
   1975 
   1976 	if( ufn != NULL ) ldap_memfree( ufn );
   1977 
   1978 	if ( attrsonly ) bvp = NULL;
   1979 
   1980 	for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp );
   1981 		rc == LDAP_SUCCESS;
   1982 		rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) )
   1983 	{
   1984 		if (bv.bv_val == NULL) break;
   1985 
   1986 		if ( attrsonly ) {
   1987 			tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 );
   1988 
   1989 		} else if ( bvals ) {
   1990 			for ( i = 0; bvals[i].bv_val != NULL; i++ ) {
   1991 				if ( vals2tmp > 1 || ( vals2tmp &&
   1992 					ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len )))
   1993 				{
   1994 					int tmpfd;
   1995 					/* write value to file */
   1996 					snprintf( tmpfname, sizeof tmpfname,
   1997 						"%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
   1998 						tmpdir, bv.bv_val );
   1999 					tmpfp = NULL;
   2000 
   2001 					tmpfd = mkstemp( tmpfname );
   2002 
   2003 					if ( tmpfd < 0  ) {
   2004 						perror( tmpfname );
   2005 						continue;
   2006 					}
   2007 
   2008 					if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) {
   2009 						perror( tmpfname );
   2010 						continue;
   2011 					}
   2012 
   2013 					if ( fwrite( bvals[ i ].bv_val,
   2014 						bvals[ i ].bv_len, 1, tmpfp ) == 0 )
   2015 					{
   2016 						perror( tmpfname );
   2017 						fclose( tmpfp );
   2018 						continue;
   2019 					}
   2020 
   2021 					fclose( tmpfp );
   2022 
   2023 					snprintf( url, sizeof url, "%s%s", urlpre,
   2024 						&tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
   2025 
   2026 					urlize( url );
   2027 					tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url ));
   2028 
   2029 				} else {
   2030 					tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val,
   2031 						bvals[ i ].bv_val, bvals[ i ].bv_len );
   2032 				}
   2033 			}
   2034 			ber_memfree( bvals );
   2035 		}
   2036 	}
   2037 
   2038 	if( ber != NULL ) {
   2039 		ber_free( ber, 0 );
   2040 	}
   2041 }
   2042 
   2043 static void print_reference(
   2044 	LDAP *ld,
   2045 	LDAPMessage *reference )
   2046 {
   2047 	int rc;
   2048 	char **refs = NULL;
   2049 	LDAPControl **ctrls;
   2050 
   2051 	if( ldif < 2 ) {
   2052 		printf(_("# search reference\n"));
   2053 	}
   2054 
   2055 	rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 );
   2056 
   2057 	if( rc != LDAP_SUCCESS ) {
   2058 		tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL );
   2059 		tool_exit( ld, EXIT_FAILURE );
   2060 	}
   2061 
   2062 	if( refs ) {
   2063 		int i;
   2064 		for( i=0; refs[i] != NULL; i++ ) {
   2065 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
   2066 				"ref", refs[i], strlen(refs[i]) );
   2067 		}
   2068 		ber_memvfree( (void **) refs );
   2069 	}
   2070 
   2071 	if( ctrls ) {
   2072 		tool_print_ctrls( ld, ctrls );
   2073 		ldap_controls_free( ctrls );
   2074 	}
   2075 }
   2076 
   2077 static void print_extended(
   2078 	LDAP *ld,
   2079 	LDAPMessage *extended )
   2080 {
   2081 	int rc;
   2082 	char *retoid = NULL;
   2083 	struct berval *retdata = NULL;
   2084 
   2085 	if( ldif < 2 ) {
   2086 		printf(_("# extended result response\n"));
   2087 	}
   2088 
   2089 	rc = ldap_parse_extended_result( ld, extended,
   2090 		&retoid, &retdata, 0 );
   2091 
   2092 	if( rc != LDAP_SUCCESS ) {
   2093 		tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
   2094 		tool_exit( ld, EXIT_FAILURE );
   2095 	}
   2096 
   2097 	if ( ldif < 2 ) {
   2098 		tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
   2099 			"extended", retoid, retoid ? strlen(retoid) : 0 );
   2100 	}
   2101 	ber_memfree( retoid );
   2102 
   2103 	if(retdata) {
   2104 		if ( ldif < 2 ) {
   2105 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
   2106 				"data", retdata->bv_val, retdata->bv_len );
   2107 		}
   2108 		ber_bvfree( retdata );
   2109 	}
   2110 
   2111 	print_result( ld, extended, 0 );
   2112 }
   2113 
   2114 static void print_syncinfo(
   2115 	BerValue *data )
   2116 {
   2117 	BerElement *syncinfo;
   2118 	struct berval bv, cookie;
   2119 	ber_tag_t tag;
   2120 	ber_len_t len;
   2121 
   2122 	if ( (syncinfo = ber_alloc()) == NULL ) {
   2123 		return;
   2124 	}
   2125 	ber_init2( syncinfo, data, 0 );
   2126 
   2127 	printf(_("# SyncInfo Received: "));
   2128 	tag = ber_peek_tag( syncinfo, &len );
   2129 	switch (tag) {
   2130 		case LDAP_TAG_SYNC_NEW_COOKIE: {
   2131 			printf(_("new cookie\n"));
   2132 			ber_scanf( syncinfo, "m", &cookie );
   2133 
   2134 			if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
   2135 				bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
   2136 						cookie.bv_len ) + 1;
   2137 				bv.bv_val = ber_memalloc( bv.bv_len + 1 );
   2138 
   2139 				bv.bv_len = lutil_b64_ntop(
   2140 						(unsigned char *) cookie.bv_val,
   2141 						cookie.bv_len,
   2142 						bv.bv_val, bv.bv_len );
   2143 
   2144 				printf(_("# cookie:: %s\n"), bv.bv_val );
   2145 				ber_memfree( bv.bv_val );
   2146 			} else {
   2147 				printf(_("# cookie: %s\n"), cookie.bv_val );
   2148 			}
   2149 			} break;
   2150 		case LDAP_TAG_SYNC_REFRESH_DELETE: {
   2151 			ber_int_t done = 1;
   2152 
   2153 			printf(_("refresh delete\n"));
   2154 			/* Skip sequence tag first */
   2155 			ber_skip_tag( syncinfo, &len );
   2156 
   2157 			tag = ber_peek_tag( syncinfo, &len );
   2158 			if ( tag == LDAP_TAG_SYNC_COOKIE ) {
   2159 				ber_scanf( syncinfo, "m", &cookie );
   2160 
   2161 				if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
   2162 					bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
   2163 							cookie.bv_len ) + 1;
   2164 					bv.bv_val = ber_memalloc( bv.bv_len + 1 );
   2165 
   2166 					bv.bv_len = lutil_b64_ntop(
   2167 							(unsigned char *) cookie.bv_val,
   2168 							cookie.bv_len,
   2169 							bv.bv_val, bv.bv_len );
   2170 
   2171 					printf(_("# cookie:: %s\n"), bv.bv_val );
   2172 					ber_memfree( bv.bv_val );
   2173 				} else {
   2174 					printf(_("# cookie: %s\n"), cookie.bv_val );
   2175 				}
   2176 
   2177 				tag = ber_peek_tag( syncinfo, &len );
   2178 			}
   2179 			if ( tag == LDAP_TAG_REFRESHDONE ) {
   2180 				ber_get_boolean( syncinfo, &done );
   2181 			}
   2182 			if ( done )
   2183 				printf(_("# refresh done, switching to persist stage\n"));
   2184 			} break;
   2185 		case LDAP_TAG_SYNC_REFRESH_PRESENT: {
   2186 			ber_int_t done = 1;
   2187 
   2188 			printf(_("refresh present\n"));
   2189 			/* Skip sequence tag first */
   2190 			ber_skip_tag( syncinfo, &len );
   2191 
   2192 			tag = ber_peek_tag( syncinfo, &len );
   2193 			if ( tag == LDAP_TAG_SYNC_COOKIE ) {
   2194 				ber_scanf( syncinfo, "m", &cookie );
   2195 
   2196 				if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
   2197 					bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
   2198 							cookie.bv_len ) + 1;
   2199 					bv.bv_val = ber_memalloc( bv.bv_len + 1 );
   2200 
   2201 					bv.bv_len = lutil_b64_ntop(
   2202 							(unsigned char *) cookie.bv_val,
   2203 							cookie.bv_len,
   2204 							bv.bv_val, bv.bv_len );
   2205 
   2206 					printf(_("# cookie:: %s\n"), bv.bv_val );
   2207 					ber_memfree( bv.bv_val );
   2208 				} else {
   2209 					printf(_("# cookie: %s\n"), cookie.bv_val );
   2210 				}
   2211 
   2212 				tag = ber_peek_tag( syncinfo, &len );
   2213 			}
   2214 			if ( tag == LDAP_TAG_REFRESHDONE ) {
   2215 				ber_get_boolean( syncinfo, &done );
   2216 			}
   2217 			if ( done )
   2218 				printf(_("# refresh done, switching to persist stage\n"));
   2219 			} break;
   2220 		case LDAP_TAG_SYNC_ID_SET: {
   2221 			ber_int_t refreshDeletes = 0;
   2222 			BerVarray uuids;
   2223 
   2224 			printf(_("ID Set\n"));
   2225 			/* Skip sequence tag first */
   2226 			ber_skip_tag( syncinfo, &len );
   2227 
   2228 			tag = ber_peek_tag( syncinfo, &len );
   2229 			if ( tag == LDAP_TAG_SYNC_COOKIE ) {
   2230 				ber_scanf( syncinfo, "m", &cookie );
   2231 
   2232 				if ( ldif_is_not_printable( cookie.bv_val, cookie.bv_len ) ) {
   2233 					bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
   2234 							cookie.bv_len ) + 1;
   2235 					bv.bv_val = ber_memalloc( bv.bv_len + 1 );
   2236 
   2237 					bv.bv_len = lutil_b64_ntop(
   2238 							(unsigned char *) cookie.bv_val,
   2239 							cookie.bv_len,
   2240 							bv.bv_val, bv.bv_len );
   2241 
   2242 					printf(_("# cookie:: %s\n"), bv.bv_val );
   2243 					ber_memfree( bv.bv_val );
   2244 				} else {
   2245 					printf(_("# cookie: %s\n"), cookie.bv_val );
   2246 				}
   2247 
   2248 				tag = ber_peek_tag( syncinfo, &len );
   2249 			}
   2250 			if ( tag == LDAP_TAG_REFRESHDELETES ) {
   2251 				ber_get_boolean( syncinfo, &refreshDeletes );
   2252 				tag = ber_peek_tag( syncinfo, &len );
   2253 			}
   2254 			if ( refreshDeletes ) {
   2255 				printf(_("# following UUIDs no longer match the search\n"));
   2256 			}
   2257 
   2258 			printf(_("# syncUUIDs:\n"));
   2259 			ber_scanf( syncinfo, "[W]", &uuids );
   2260 			if ( uuids ) {
   2261 				char buf[LDAP_LUTIL_UUIDSTR_BUFSIZE];
   2262 				int i;
   2263 
   2264 				for ( i=0; !BER_BVISNULL( &uuids[i] ); i++ ) {
   2265 					int rc = lutil_uuidstr_from_normalized(
   2266 							uuids[i].bv_val, uuids[i].bv_len,
   2267 							buf, LDAP_LUTIL_UUIDSTR_BUFSIZE );
   2268 					if ( rc <= 0 || rc >= LDAP_LUTIL_UUIDSTR_BUFSIZE ) {
   2269 						printf(_("#\t(UUID malformed)\n"));
   2270 					} else {
   2271 						printf(_("#\t%s\n"), buf);
   2272 					}
   2273 				}
   2274 				ber_bvarray_free( uuids );
   2275 			}
   2276 			} break;
   2277 		case LBER_DEFAULT:
   2278 			printf(_("empty SyncInfoValue\n"));
   2279 		default:
   2280 			printf(_("SyncInfoValue unknown\n"));
   2281 			break;
   2282 	}
   2283 	ber_free( syncinfo, 0 );
   2284 }
   2285 
   2286 static void print_partial(
   2287 	LDAP *ld,
   2288 	LDAPMessage *partial )
   2289 {
   2290 	int rc;
   2291 	char *retoid = NULL;
   2292 	struct berval *retdata = NULL;
   2293 	LDAPControl **ctrls = NULL;
   2294 
   2295 	if( ldif < 2 ) {
   2296 		printf(_("# extended partial response\n"));
   2297 	}
   2298 
   2299 	rc = ldap_parse_intermediate( ld, partial,
   2300 		&retoid, &retdata, &ctrls, 0 );
   2301 
   2302 	if( rc != LDAP_SUCCESS ) {
   2303 		tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL );
   2304 		tool_exit( ld, EXIT_FAILURE );
   2305 	}
   2306 
   2307 	if ( ldif < 2 ) {
   2308 		tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
   2309 			"partial", retoid, retoid ? strlen(retoid) : 0 );
   2310 	}
   2311 
   2312 	ber_memfree( retoid );
   2313 
   2314 	if( retdata ) {
   2315 		if ( ldif < 2 ) {
   2316 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
   2317 				"data", retdata->bv_val, retdata->bv_len );
   2318 		}
   2319 
   2320 		ber_bvfree( retdata );
   2321 	}
   2322 
   2323 	if( ctrls ) {
   2324 		tool_print_ctrls( ld, ctrls );
   2325 		ldap_controls_free( ctrls );
   2326 	}
   2327 }
   2328 
   2329 static int print_result(
   2330 	LDAP *ld,
   2331 	LDAPMessage *result, int search )
   2332 {
   2333 	int rc;
   2334 	int err;
   2335 	char *matcheddn = NULL;
   2336 	char *text = NULL;
   2337 	char **refs = NULL;
   2338 	LDAPControl **ctrls = NULL;
   2339 
   2340 	if( search ) {
   2341 		if ( ldif < 2 ) {
   2342 			printf(_("# search result\n"));
   2343 		}
   2344 		if ( ldif < 1 ) {
   2345 			printf("%s: %d\n", _("search"), ldap_msgid(result) );
   2346 		}
   2347 	}
   2348 
   2349 	rc = ldap_parse_result( ld, result,
   2350 		&err, &matcheddn, &text, &refs, &ctrls, 0 );
   2351 
   2352 	if( rc != LDAP_SUCCESS ) {
   2353 		tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
   2354 		tool_exit( ld, EXIT_FAILURE );
   2355 	}
   2356 
   2357 
   2358 	if( !ldif ) {
   2359 		printf( _("result: %d %s\n"), err, ldap_err2string(err) );
   2360 
   2361 	} else if ( err != LDAP_SUCCESS ) {
   2362 		fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err );
   2363 	}
   2364 
   2365 	if( matcheddn ) {
   2366 		if( *matcheddn ) {
   2367 		if( !ldif ) {
   2368 			tool_write_ldif( LDIF_PUT_VALUE,
   2369 				"matchedDN", matcheddn, strlen(matcheddn) );
   2370 		} else {
   2371 			fprintf( stderr, _("Matched DN: %s\n"), matcheddn );
   2372 		}
   2373 		}
   2374 
   2375 		ber_memfree( matcheddn );
   2376 	}
   2377 
   2378 	if( text ) {
   2379 		if( *text ) {
   2380 			if( !ldif ) {
   2381 				if ( err == LDAP_PARTIAL_RESULTS ) {
   2382 					char	*line;
   2383 
   2384 					for ( line = text; line != NULL; ) {
   2385 						char	*next = strchr( line, '\n' );
   2386 
   2387 						tool_write_ldif( LDIF_PUT_TEXT,
   2388 							"text", line,
   2389 							next ? (size_t) (next - line) : strlen( line ));
   2390 
   2391 						line = next ? next + 1 : NULL;
   2392 					}
   2393 
   2394 				} else {
   2395 					tool_write_ldif( LDIF_PUT_TEXT, "text",
   2396 						text, strlen(text) );
   2397 				}
   2398 			} else {
   2399 				fprintf( stderr, _("Additional information: %s\n"), text );
   2400 			}
   2401 		}
   2402 
   2403 		ber_memfree( text );
   2404 	}
   2405 
   2406 	if( refs ) {
   2407 		int i;
   2408 		for( i=0; refs[i] != NULL; i++ ) {
   2409 			if( !ldif ) {
   2410 				tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) );
   2411 			} else {
   2412 				fprintf( stderr, _("Referral: %s\n"), refs[i] );
   2413 			}
   2414 		}
   2415 
   2416 		ber_memvfree( (void **) refs );
   2417 	}
   2418 
   2419 	pr_morePagedResults = 0;
   2420 
   2421 	if( ctrls ) {
   2422 		tool_print_ctrls( ld, ctrls );
   2423 		ldap_controls_free( ctrls );
   2424 	}
   2425 
   2426 	return err;
   2427 }
   2428