xref: /netbsd-src/external/bsd/openldap/dist/clients/tools/ldapsearch.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: ldapsearch.c,v 1.1.1.4 2014/05/28 09:58:22 tron 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-2014 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 "portable.h"
42 
43 #include <stdio.h>
44 
45 #include <ac/stdlib.h>
46 #include <ac/ctype.h>
47 #include <ac/string.h>
48 #include <ac/unistd.h>
49 #include <ac/errno.h>
50 #include <ac/time.h>
51 
52 #include <sys/stat.h>
53 
54 #include <ac/signal.h>
55 
56 #ifdef HAVE_FCNTL_H
57 #include <fcntl.h>
58 #endif
59 #ifdef HAVE_SYS_TYPES_H
60 #include <sys/types.h>
61 #endif
62 #ifdef HAVE_IO_H
63 #include <io.h>
64 #endif
65 
66 #include <ldap.h>
67 
68 #include "ldif.h"
69 #include "lutil.h"
70 #include "lutil_ldap.h"
71 #include "ldap_defaults.h"
72 #include "ldap_pvt.h"
73 
74 #include "common.h"
75 
76 #if !LDAP_DEPRECATED
77 /*
78  * NOTE: we use this deprecated function only because
79  * we want ldapsearch to provide some client-side sorting
80  * capability.
81  */
82 /* from ldap.h */
83 typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */
84 	LDAP_CONST char *left,
85 	LDAP_CONST char *right ));
86 
87 LDAP_F( int )	/* deprecated */
88 ldap_sort_entries LDAP_P(( LDAP *ld,
89 	LDAPMessage **chain,
90 	LDAP_CONST char *attr,
91 	LDAP_SORT_AD_CMP_PROC *cmp ));
92 #endif
93 
94 static int scope = LDAP_SCOPE_SUBTREE;
95 static int deref = -1;
96 static int attrsonly;
97 static int timelimit = -1;
98 static int sizelimit = -1;
99 
100 static char *control;
101 
102 static char *def_tmpdir;
103 static char *def_urlpre;
104 
105 #if defined(__CYGWIN__) || defined(__MINGW32__)
106 /* Turn off commandline globbing, otherwise you cannot search for
107  * attribute '*'
108  */
109 int _CRT_glob = 0;
110 #endif
111 
112 void
113 usage( void )
114 {
115 	fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog);
116 	fprintf( stderr, _("  filter\tRFC 4515 compliant LDAP search filter\n"));
117 	fprintf( stderr, _("  attributes\twhitespace-separated list of attribute descriptions\n"));
118 	fprintf( stderr, _("    which may include:\n"));
119 	fprintf( stderr, _("      1.1   no attributes\n"));
120 	fprintf( stderr, _("      *     all user attributes\n"));
121 	fprintf( stderr, _("      +     all operational attributes\n"));
122 
123 
124 	fprintf( stderr, _("Search options:\n"));
125 	fprintf( stderr, _("  -a deref   one of never (default), always, search, or find\n"));
126 	fprintf( stderr, _("  -A         retrieve attribute names only (no values)\n"));
127 	fprintf( stderr, _("  -b basedn  base dn for search\n"));
128 	fprintf( stderr, _("  -c         continuous operation mode (do not stop on errors)\n"));
129 	fprintf( stderr, _("  -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n"));
130 	fprintf( stderr, _("             [!]domainScope              (domain scope)\n"));
131 	fprintf( stderr, _("             !dontUseCopy                (Don't Use Copy)\n"));
132 	fprintf( stderr, _("             [!]mv=<filter>              (RFC 3876 matched values filter)\n"));
133 	fprintf( stderr, _("             [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
134 	fprintf( stderr, _("             [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
135 	fprintf( stderr, _("                                         (RFC 2891 server side sorting)\n"));
136 	fprintf( stderr, _("             [!]subentries[=true|false]  (RFC 3672 subentries)\n"));
137 	fprintf( stderr, _("             [!]sync=ro[/<cookie>]       (RFC 4533 LDAP Sync refreshOnly)\n"));
138 	fprintf( stderr, _("                     rp[/<cookie>][/<slimit>] (refreshAndPersist)\n"));
139 	fprintf( stderr, _("             [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n"));
140 	fprintf( stderr, _("                                         (ldapv3-vlv-09 virtual list views)\n"));
141 #ifdef LDAP_CONTROL_X_DEREF
142 	fprintf( stderr, _("             [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
143 #endif
144 	fprintf( stderr, _("             [!]<oid>[=:<b64value>] (generic control; no response handling)\n"));
145 	fprintf( stderr, _("  -f file    read operations from `file'\n"));
146 	fprintf( stderr, _("  -F prefix  URL prefix for files (default: %s)\n"), def_urlpre);
147 	fprintf( stderr, _("  -l limit   time limit (in seconds, or \"none\" or \"max\") for search\n"));
148 	fprintf( stderr, _("  -L         print responses in LDIFv1 format\n"));
149 	fprintf( stderr, _("  -LL        print responses in LDIF format without comments\n"));
150 	fprintf( stderr, _("  -LLL       print responses in LDIF format without comments\n"));
151 	fprintf( stderr, _("             and version\n"));
152 	fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
153 	fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
154 	fprintf( stderr, _("  -s scope   one of base, one, sub or children (search scope)\n"));
155 	fprintf( stderr, _("  -S attr    sort the results by attribute `attr'\n"));
156 	fprintf( stderr, _("  -t         write binary values to files in temporary directory\n"));
157 	fprintf( stderr, _("  -tt        write all values to files in temporary directory\n"));
158 	fprintf( stderr, _("  -T path    write files to directory specified by path (default: %s)\n"), def_tmpdir);
159 	fprintf( stderr, _("  -u         include User Friendly entry names in the output\n"));
160 	fprintf( stderr, _("  -z limit   size limit (in entries, or \"none\" or \"max\") for search\n"));
161 	tool_common_usage();
162 	exit( EXIT_FAILURE );
163 }
164 
165 static void print_entry LDAP_P((
166 	LDAP	*ld,
167 	LDAPMessage	*entry,
168 	int		attrsonly));
169 
170 static void print_reference(
171 	LDAP *ld,
172 	LDAPMessage *reference );
173 
174 static void print_extended(
175 	LDAP *ld,
176 	LDAPMessage *extended );
177 
178 static void print_partial(
179 	LDAP *ld,
180 	LDAPMessage *partial );
181 
182 static int print_result(
183 	LDAP *ld,
184 	LDAPMessage *result,
185 	int search );
186 
187 static int dosearch LDAP_P((
188 	LDAP	*ld,
189 	char	*base,
190 	int		scope,
191 	char	*filtpatt,
192 	char	*value,
193 	char	**attrs,
194 	int		attrsonly,
195 	LDAPControl **sctrls,
196 	LDAPControl **cctrls,
197 	struct timeval *timeout,
198 	int	sizelimit ));
199 
200 static char *tmpdir = NULL;
201 static char *urlpre = NULL;
202 static char	*base = NULL;
203 static char	*sortattr = NULL;
204 static int  includeufn, vals2tmp = 0;
205 
206 static int subentries = 0, valuesReturnFilter = 0;
207 static char	*vrFilter = NULL;
208 
209 #ifdef LDAP_CONTROL_DONTUSECOPY
210 static int dontUseCopy = 0;
211 #endif
212 
213 static int domainScope = 0;
214 
215 static int sss = 0;
216 static LDAPSortKey **sss_keys = NULL;
217 
218 static int vlv = 0;
219 static LDAPVLVInfo vlvInfo;
220 static struct berval vlvValue;
221 
222 static int ldapsync = 0;
223 static struct berval sync_cookie = { 0, NULL };
224 static int sync_slimit = -1;
225 
226 /* cookie and morePagedResults moved to common.c */
227 static int pagedResults = 0;
228 static int pagePrompt = 1;
229 static ber_int_t pageSize = 0;
230 static ber_int_t entriesLeft = 0;
231 static int npagedresponses;
232 static int npagedentries;
233 static int npagedreferences;
234 static int npagedextended;
235 static int npagedpartial;
236 
237 static LDAPControl *c = NULL;
238 static int nctrls = 0;
239 static int save_nctrls = 0;
240 
241 #ifdef LDAP_CONTROL_X_DEREF
242 static int derefcrit;
243 static LDAPDerefSpec *ds;
244 static struct berval derefval;
245 #endif
246 
247 static int
248 ctrl_add( void )
249 {
250 	LDAPControl	*tmpc;
251 
252 	nctrls++;
253 	tmpc = realloc( c, sizeof( LDAPControl ) * nctrls );
254 	if ( tmpc == NULL ) {
255 		nctrls--;
256 		fprintf( stderr,
257 			_("unable to make room for control; out of memory?\n"));
258 		return -1;
259 	}
260 	c = tmpc;
261 
262 	return 0;
263 }
264 
265 static void
266 urlize(char *url)
267 {
268 	char *p;
269 
270 	if (*LDAP_DIRSEP != '/') {
271 		for (p = url; *p; p++) {
272 			if (*p == *LDAP_DIRSEP)
273 				*p = '/';
274 		}
275 	}
276 }
277 
278 static int
279 parse_vlv(char *cvalue)
280 {
281 	char *keyp, *key2;
282 	int num1, num2;
283 
284 	keyp = cvalue;
285 	if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
286 		fprintf( stderr,
287 			_("VLV control value \"%s\" invalid\n"),
288 			cvalue );
289 		return -1;
290 	}
291 	vlvInfo.ldvlv_before_count = num1;
292 	vlvInfo.ldvlv_after_count = num2;
293 	keyp = strchr( keyp, '/' ) + 1;
294 	key2 = strchr( keyp, '/' );
295 	if ( key2 ) {
296 		keyp = key2 + 1;
297 		if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
298 			fprintf( stderr,
299 				_("VLV control value \"%s\" invalid\n"),
300 				cvalue );
301 			return -1;
302 		}
303 		vlvInfo.ldvlv_offset = num1;
304 		vlvInfo.ldvlv_count = num2;
305 		vlvInfo.ldvlv_attrvalue = NULL;
306 	} else {
307 		key2 = strchr( keyp, ':' );
308 		if ( !key2 ) {
309 			fprintf( stderr,
310 				_("VLV control value \"%s\" invalid\n"),
311 				cvalue );
312 			return -1;
313 		}
314 		ber_str2bv( key2+1, 0, 0, &vlvValue );
315 		vlvInfo.ldvlv_attrvalue = &vlvValue;
316 	}
317 	return 0;
318 }
319 
320 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
321 	"Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
322 
323 int
324 handle_private_option( int i )
325 {
326 	int crit, ival;
327 	char *cvalue, *next;
328 	switch ( i ) {
329 	case 'a':	/* set alias deref option */
330 		if ( strcasecmp( optarg, "never" ) == 0 ) {
331 			deref = LDAP_DEREF_NEVER;
332 		} else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
333 			deref = LDAP_DEREF_SEARCHING;
334 		} else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
335 			deref = LDAP_DEREF_FINDING;
336 		} else if ( strcasecmp( optarg, "always" ) == 0 ) {
337 			deref = LDAP_DEREF_ALWAYS;
338 		} else {
339 			fprintf( stderr,
340 				_("alias deref should be never, search, find, or always\n") );
341 			usage();
342 		}
343 		break;
344 	case 'A':	/* retrieve attribute names only -- no values */
345 		++attrsonly;
346 		break;
347 	case 'b': /* search base */
348 		base = ber_strdup( optarg );
349 		break;
350 	case 'E': /* search extensions */
351 		if( protocol == LDAP_VERSION2 ) {
352 			fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
353 				prog, protocol );
354 			exit( EXIT_FAILURE );
355 		}
356 
357 		/* should be extended to support comma separated list of
358 		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
359 		 */
360 
361 		crit = 0;
362 		cvalue = NULL;
363 		if( optarg[0] == '!' ) {
364 			crit = 1;
365 			optarg++;
366 		}
367 
368 		control = ber_strdup( optarg );
369 		if ( (cvalue = strchr( control, '=' )) != NULL ) {
370 			*cvalue++ = '\0';
371 		}
372 
373 		if ( strcasecmp( control, "mv" ) == 0 ) {
374 			/* ValuesReturnFilter control */
375 			if( valuesReturnFilter ) {
376 				fprintf( stderr,
377 					_("ValuesReturnFilter previously specified\n"));
378 				exit( EXIT_FAILURE );
379 			}
380 			valuesReturnFilter= 1 + crit;
381 
382 			if ( cvalue == NULL ) {
383 				fprintf( stderr,
384 					_("missing filter in ValuesReturnFilter control\n"));
385 				exit( EXIT_FAILURE );
386 			}
387 
388 			vrFilter = cvalue;
389 			protocol = LDAP_VERSION3;
390 
391 		} else if ( strcasecmp( control, "pr" ) == 0 ) {
392 			int num, tmp;
393 			/* PagedResults control */
394 			if ( pagedResults != 0 ) {
395 				fprintf( stderr,
396 					_("PagedResultsControl previously specified\n") );
397 				exit( EXIT_FAILURE );
398 			}
399 			if ( vlv != 0 ) {
400 				fprintf( stderr,
401 					_("PagedResultsControl incompatible with VLV\n") );
402 				exit( EXIT_FAILURE );
403 			}
404 
405 			if( cvalue != NULL ) {
406 				char *promptp;
407 
408 				promptp = strchr( cvalue, '/' );
409 				if ( promptp != NULL ) {
410 					*promptp++ = '\0';
411 					if ( strcasecmp( promptp, "prompt" ) == 0 ) {
412 						pagePrompt = 1;
413 					} else if ( strcasecmp( promptp, "noprompt" ) == 0) {
414 						pagePrompt = 0;
415 					} else {
416 						fprintf( stderr,
417 							_("Invalid value for PagedResultsControl,"
418 							" %s/%s.\n"), cvalue, promptp );
419 						exit( EXIT_FAILURE );
420 					}
421 				}
422 				num = sscanf( cvalue, "%d", &tmp );
423 				if ( num != 1 ) {
424 					fprintf( stderr,
425 						_("Invalid value for PagedResultsControl, %s.\n"),
426 						cvalue );
427 					exit( EXIT_FAILURE );
428 				}
429 			} else {
430 				fprintf(stderr, _("Invalid value for PagedResultsControl.\n"));
431 				exit( EXIT_FAILURE );
432 			}
433 			pageSize = (ber_int_t) tmp;
434 			pagedResults = 1 + crit;
435 
436 #ifdef LDAP_CONTROL_DONTUSECOPY
437 		} else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
438 			if( dontUseCopy ) {
439 				fprintf( stderr,
440 					_("dontUseCopy control previously specified\n"));
441 				exit( EXIT_FAILURE );
442 			}
443 			if( cvalue != NULL ) {
444 				fprintf( stderr,
445 			         _("dontUseCopy: no control value expected\n") );
446 				usage();
447 			}
448 			if( !crit ) {
449 				fprintf( stderr,
450 			         _("dontUseCopy: critical flag required\n") );
451 				usage();
452 			}
453 
454 			dontUseCopy = 1 + crit;
455 #endif
456 		} else if ( strcasecmp( control, "domainScope" ) == 0 ) {
457 			if( domainScope ) {
458 				fprintf( stderr,
459 					_("domainScope control previously specified\n"));
460 				exit( EXIT_FAILURE );
461 			}
462 			if( cvalue != NULL ) {
463 				fprintf( stderr,
464 			         _("domainScope: no control value expected\n") );
465 				usage();
466 			}
467 
468 			domainScope = 1 + crit;
469 
470 		} else if ( strcasecmp( control, "sss" ) == 0 ) {
471 			char *keyp;
472 			if( sss ) {
473 				fprintf( stderr,
474 					_("server side sorting control previously specified\n"));
475 				exit( EXIT_FAILURE );
476 			}
477 			if( cvalue == NULL ) {
478 				fprintf( stderr,
479 			         _("missing specification of sss control\n") );
480 				exit( EXIT_FAILURE );
481 			}
482 			keyp = cvalue;
483 			while ( ( keyp = strchr(keyp, '/') ) != NULL ) {
484 				*keyp++ = ' ';
485 			}
486 			if ( ldap_create_sort_keylist( &sss_keys, cvalue )) {
487 				fprintf( stderr,
488 					_("server side sorting control value \"%s\" invalid\n"),
489 					cvalue );
490 				exit( EXIT_FAILURE );
491 			}
492 
493 			sss = 1 + crit;
494 
495 		} else if ( strcasecmp( control, "subentries" ) == 0 ) {
496 			if( subentries ) {
497 				fprintf( stderr,
498 					_("subentries control previously specified\n"));
499 				exit( EXIT_FAILURE );
500 			}
501 			if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) {
502 				subentries = 2;
503 			} else if ( strcasecmp( cvalue, "false") == 0 ) {
504 				subentries = 1;
505 			} else {
506 				fprintf( stderr,
507 					_("subentries control value \"%s\" invalid\n"),
508 					cvalue );
509 				exit( EXIT_FAILURE );
510 			}
511 			if( crit ) subentries *= -1;
512 
513 		} else if ( strcasecmp( control, "sync" ) == 0 ) {
514 			char *cookiep;
515 			char *slimitp;
516 			if ( ldapsync ) {
517 				fprintf( stderr, _("sync control previously specified\n") );
518 				exit( EXIT_FAILURE );
519 			}
520 			if ( cvalue == NULL ) {
521 				fprintf( stderr, _("missing specification of sync control\n"));
522 				exit( EXIT_FAILURE );
523 			}
524 			if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
525 				ldapsync = LDAP_SYNC_REFRESH_ONLY;
526 				cookiep = strchr( cvalue, '/' );
527 				if ( cookiep != NULL ) {
528 					cookiep++;
529 					if ( *cookiep != '\0' ) {
530 						ber_str2bv( cookiep, 0, 0, &sync_cookie );
531 					}
532 				}
533 			} else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
534 				ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
535 				cookiep = strchr( cvalue, '/' );
536 				if ( cookiep != NULL ) {
537 					*cookiep++ = '\0';
538 					cvalue = cookiep;
539 				}
540 				slimitp = strchr( cvalue, '/' );
541 				if ( slimitp != NULL ) {
542 					*slimitp++ = '\0';
543 				}
544 				if ( cookiep != NULL && *cookiep != '\0' )
545 					ber_str2bv( cookiep, 0, 0, &sync_cookie );
546 				if ( slimitp != NULL && *slimitp != '\0' ) {
547 					ival = strtol( slimitp, &next, 10 );
548 					if ( next == NULL || next[0] != '\0' ) {
549 						fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp );
550 						exit( EXIT_FAILURE );
551 					}
552 					sync_slimit = ival;
553 				}
554 			} else {
555 				fprintf( stderr, _("sync control value \"%s\" invalid\n"),
556 					cvalue );
557 				exit( EXIT_FAILURE );
558 			}
559 			if ( crit ) ldapsync *= -1;
560 
561 		} else if ( strcasecmp( control, "vlv" ) == 0 ) {
562 			if( vlv ) {
563 				fprintf( stderr,
564 					_("virtual list view control previously specified\n"));
565 				exit( EXIT_FAILURE );
566 			}
567 			if ( pagedResults != 0 ) {
568 				fprintf( stderr,
569 					_("PagedResultsControl incompatible with VLV\n") );
570 				exit( EXIT_FAILURE );
571 			}
572 			if( cvalue == NULL ) {
573 				fprintf( stderr,
574 			         _("missing specification of vlv control\n") );
575 				exit( EXIT_FAILURE );
576 			}
577 			if ( parse_vlv( cvalue ))
578 				exit( EXIT_FAILURE );
579 
580 			vlv = 1 + crit;
581 
582 #ifdef LDAP_CONTROL_X_DEREF
583 		} else if ( strcasecmp( control, "deref" ) == 0 ) {
584 			int ispecs;
585 			char **specs;
586 
587 			/* cvalue is something like
588 			 *
589 			 * derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]"
590 			 */
591 
592 			specs = ldap_str2charray( cvalue, ";" );
593 			if ( specs == NULL ) {
594 				fprintf( stderr, _("deref specs \"%s\" invalid\n"),
595 					cvalue );
596 				exit( EXIT_FAILURE );
597 			}
598 			for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
599 				/* count'em */ ;
600 
601 			ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
602 			if ( ds == NULL ) {
603 				perror( "malloc" );
604 				exit( EXIT_FAILURE );
605 			}
606 
607 			for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
608 				char *ptr;
609 
610 				ptr = strchr( specs[ ispecs ], ':' );
611 				if ( ptr == NULL ) {
612 					fprintf( stderr, _("deref specs \"%s\" invalid\n"),
613 						cvalue );
614 					exit( EXIT_FAILURE );
615 				}
616 
617 				ds[ ispecs ].derefAttr = specs[ ispecs ];
618 				*ptr++ = '\0';
619 				ds[ ispecs ].attributes = ldap_str2charray( ptr, "," );
620 			}
621 
622 			derefcrit = 1 + crit;
623 
624 			ldap_memfree( specs );
625 #endif /* LDAP_CONTROL_X_DEREF */
626 
627 		} else if ( tool_is_oid( control ) ) {
628 			if ( ctrl_add() ) {
629 				exit( EXIT_FAILURE );
630 			}
631 
632 			/* OID */
633 			c[ nctrls - 1 ].ldctl_oid = control;
634 
635 			/* value */
636 			if ( cvalue == NULL ) {
637 				c[ nctrls - 1 ].ldctl_value.bv_val = NULL;
638 				c[ nctrls - 1 ].ldctl_value.bv_len = 0;
639 
640 			} else if ( cvalue[ 0 ] == ':' ) {
641 				struct berval type;
642 				struct berval value;
643 				int freeval;
644 				char save_c;
645 
646 				cvalue++;
647 
648 				/* dummy type "x"
649 				 * to use ldif_parse_line2() */
650 				save_c = cvalue[ -2 ];
651 				cvalue[ -2 ] = 'x';
652 				ldif_parse_line2( &cvalue[ -2 ], &type,
653 					&value, &freeval );
654 				cvalue[ -2 ] = save_c;
655 
656 				if ( freeval ) {
657 					c[ nctrls - 1 ].ldctl_value = value;
658 
659 				} else {
660 					ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value );
661 				}
662 
663 			} else {
664 				fprintf( stderr, "unable to parse %s control value\n", control );
665 				exit( EXIT_FAILURE );
666 
667 			}
668 
669 			/* criticality */
670 			c[ nctrls - 1 ].ldctl_iscritical = crit;
671 
672 		} else {
673 			fprintf( stderr, _("Invalid search extension name: %s\n"),
674 				control );
675 			usage();
676 		}
677 		break;
678 	case 'F':	/* uri prefix */
679 		if( urlpre ) free( urlpre );
680 		urlpre = strdup( optarg );
681 		break;
682 	case 'l':	/* time limit */
683 		if ( strcasecmp( optarg, "none" ) == 0 ) {
684 			timelimit = 0;
685 
686 		} else if ( strcasecmp( optarg, "max" ) == 0 ) {
687 			timelimit = LDAP_MAXINT;
688 
689 		} else {
690 			ival = strtol( optarg, &next, 10 );
691 			if ( next == NULL || next[0] != '\0' ) {
692 				fprintf( stderr,
693 					_("Unable to parse time limit \"%s\"\n"), optarg );
694 				exit( EXIT_FAILURE );
695 			}
696 			timelimit = ival;
697 		}
698 		if( timelimit < 0 || timelimit > LDAP_MAXINT ) {
699 			fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"),
700 				prog, timelimit );
701 			exit( EXIT_FAILURE );
702 		}
703 		break;
704 	case 'L':	/* print entries in LDIF format */
705 		++ldif;
706 		break;
707 	case 's':	/* search scope */
708 		if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) {
709 			scope = LDAP_SCOPE_BASE;
710 		} else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) {
711 			scope = LDAP_SCOPE_ONELEVEL;
712 		} else if (( strcasecmp( optarg, "subordinate" ) == 0 )
713 			|| ( strcasecmp( optarg, "children" ) == 0 ))
714 		{
715 			scope = LDAP_SCOPE_SUBORDINATE;
716 		} else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) {
717 			scope = LDAP_SCOPE_SUBTREE;
718 		} else {
719 			fprintf( stderr, _("scope should be base, one, or sub\n") );
720 			usage();
721 		}
722 		break;
723 	case 'S':	/* sort attribute */
724 		sortattr = strdup( optarg );
725 		break;
726 	case 't':	/* write attribute values to TMPDIR files */
727 		++vals2tmp;
728 		break;
729 	case 'T':	/* tmpdir */
730 		if( tmpdir ) free( tmpdir );
731 		tmpdir = strdup( optarg );
732 		break;
733 	case 'u':	/* include UFN */
734 		++includeufn;
735 		break;
736 	case 'z':	/* size limit */
737 		if ( strcasecmp( optarg, "none" ) == 0 ) {
738 			sizelimit = 0;
739 
740 		} else if ( strcasecmp( optarg, "max" ) == 0 ) {
741 			sizelimit = LDAP_MAXINT;
742 
743 		} else {
744 			ival = strtol( optarg, &next, 10 );
745 			if ( next == NULL || next[0] != '\0' ) {
746 				fprintf( stderr,
747 					_("Unable to parse size limit \"%s\"\n"), optarg );
748 				exit( EXIT_FAILURE );
749 			}
750 			sizelimit = ival;
751 		}
752 		if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) {
753 			fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"),
754 				prog, sizelimit );
755 			exit( EXIT_FAILURE );
756 		}
757 		break;
758 	default:
759 		return 0;
760 	}
761 	return 1;
762 }
763 
764 
765 static void
766 private_conn_setup( LDAP *ld )
767 {
768 	if (deref != -1 &&
769 		ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref )
770 			!= LDAP_OPT_SUCCESS )
771 	{
772 		fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref );
773 		tool_exit( ld, EXIT_FAILURE );
774 	}
775 }
776 
777 int
778 main( int argc, char **argv )
779 {
780 	char		*filtpattern, **attrs = NULL, line[BUFSIZ];
781 	FILE		*fp = NULL;
782 	int			rc, rc1, i, first;
783 	LDAP		*ld = NULL;
784 	BerElement	*seber = NULL, *vrber = NULL;
785 
786 	BerElement      *syncber = NULL;
787 	struct berval   *syncbvalp = NULL;
788 	int		err;
789 
790 	tool_init( TOOL_SEARCH );
791 
792 	npagedresponses = npagedentries = npagedreferences =
793 		npagedextended = npagedpartial = 0;
794 
795 	prog = lutil_progname( "ldapsearch", argc, argv );
796 
797 	if((def_tmpdir = getenv("TMPDIR")) == NULL &&
798 	   (def_tmpdir = getenv("TMP")) == NULL &&
799 	   (def_tmpdir = getenv("TEMP")) == NULL )
800 	{
801 		def_tmpdir = LDAP_TMPDIR;
802 	}
803 
804 	if ( !*def_tmpdir )
805 		def_tmpdir = LDAP_TMPDIR;
806 
807 	def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
808 
809 	if( def_urlpre == NULL ) {
810 		perror( "malloc" );
811 		return EXIT_FAILURE;
812 	}
813 
814 	sprintf( def_urlpre, "file:///%s/",
815 		def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
816 
817 	urlize( def_urlpre );
818 
819 	tool_args( argc, argv );
820 
821 	if ( vlv && !sss ) {
822 		fprintf( stderr,
823 			_("VLV control requires server side sort control\n" ));
824 		return EXIT_FAILURE;
825 	}
826 
827 	if (( argc - optind < 1 ) ||
828 		( *argv[optind] != '(' /*')'*/ &&
829 		( strchr( argv[optind], '=' ) == NULL ) ) )
830 	{
831 		filtpattern = "(objectclass=*)";
832 	} else {
833 		filtpattern = argv[optind++];
834 	}
835 
836 	if ( argv[optind] != NULL ) {
837 		attrs = &argv[optind];
838 	}
839 
840 	if ( infile != NULL ) {
841 		int percent = 0;
842 
843 		if ( infile[0] == '-' && infile[1] == '\0' ) {
844 			fp = stdin;
845 		} else if (( fp = fopen( infile, "r" )) == NULL ) {
846 			perror( infile );
847 			return EXIT_FAILURE;
848 		}
849 
850 		for( i=0 ; filtpattern[i] ; i++ ) {
851 			if( filtpattern[i] == '%' ) {
852 				if( percent ) {
853 					fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
854 						filtpattern );
855 					return EXIT_FAILURE;
856 				}
857 
858 				percent++;
859 
860 				if( filtpattern[i+1] != 's' ) {
861 					fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
862 						filtpattern );
863 					return EXIT_FAILURE;
864 				}
865 			}
866 		}
867 	}
868 
869 	if ( tmpdir == NULL ) {
870 		tmpdir = def_tmpdir;
871 
872 		if ( urlpre == NULL )
873 			urlpre = def_urlpre;
874 	}
875 
876 	if( urlpre == NULL ) {
877 		urlpre = malloc( sizeof("file:////") + strlen(tmpdir) );
878 
879 		if( urlpre == NULL ) {
880 			perror( "malloc" );
881 			return EXIT_FAILURE;
882 		}
883 
884 		sprintf( urlpre, "file:///%s/",
885 			tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir );
886 
887 		urlize( urlpre );
888 	}
889 
890 	if ( debug )
891 		ldif_debug = debug;
892 
893 	ld = tool_conn_setup( 0, &private_conn_setup );
894 
895 	tool_bind( ld );
896 
897 getNextPage:
898 	/* fp may have been closed, need to reopen if code jumps
899 	 * back here to getNextPage.
900 	 */
901 	if ( !fp && infile ) {
902 		if (( fp = fopen( infile, "r" )) == NULL ) {
903 			perror( infile );
904 			tool_exit( ld, EXIT_FAILURE );
905 		}
906 	}
907 	save_nctrls = nctrls;
908 	i = nctrls;
909 	if ( nctrls > 0
910 #ifdef LDAP_CONTROL_DONTUSECOPY
911 		|| dontUseCopy
912 #endif
913 #ifdef LDAP_CONTROL_X_DEREF
914 		|| derefcrit
915 #endif
916 		|| domainScope
917 		|| pagedResults
918 		|| ldapsync
919 		|| sss
920 		|| subentries
921 		|| valuesReturnFilter
922 		|| vlv )
923 	{
924 
925 #ifdef LDAP_CONTROL_DONTUSECOPY
926 		if ( dontUseCopy ) {
927 			if ( ctrl_add() ) {
928 				tool_exit( ld, EXIT_FAILURE );
929 			}
930 
931 			c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
932 			c[i].ldctl_value.bv_val = NULL;
933 			c[i].ldctl_value.bv_len = 0;
934 			c[i].ldctl_iscritical = dontUseCopy > 1;
935 			i++;
936 		}
937 #endif
938 
939 		if ( domainScope ) {
940 			if ( ctrl_add() ) {
941 				tool_exit( ld, EXIT_FAILURE );
942 			}
943 
944 			c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
945 			c[i].ldctl_value.bv_val = NULL;
946 			c[i].ldctl_value.bv_len = 0;
947 			c[i].ldctl_iscritical = domainScope > 1;
948 			i++;
949 		}
950 
951 		if ( subentries ) {
952 			if ( ctrl_add() ) {
953 				tool_exit( ld, EXIT_FAILURE );
954 			}
955 
956 			if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
957 				tool_exit( ld, EXIT_FAILURE );
958 			}
959 
960 			err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
961 			if ( err == -1 ) {
962 				ber_free( seber, 1 );
963 				fprintf( stderr, _("Subentries control encoding error!\n") );
964 				tool_exit( ld, EXIT_FAILURE );
965 			}
966 
967 			if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) {
968 				tool_exit( ld, EXIT_FAILURE );
969 			}
970 
971 			c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES;
972 			c[i].ldctl_iscritical = subentries < 1;
973 			i++;
974 		}
975 
976 		if ( ldapsync ) {
977 			if ( ctrl_add() ) {
978 				tool_exit( ld, EXIT_FAILURE );
979 			}
980 
981 			if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
982 				tool_exit( ld, EXIT_FAILURE );
983 			}
984 
985 			if ( sync_cookie.bv_len == 0 ) {
986 				err = ber_printf( syncber, "{e}", abs(ldapsync) );
987 			} else {
988 				err = ber_printf( syncber, "{eO}", abs(ldapsync),
989 							&sync_cookie );
990 			}
991 
992 			if ( err == -1 ) {
993 				ber_free( syncber, 1 );
994 				fprintf( stderr, _("ldap sync control encoding error!\n") );
995 				tool_exit( ld, EXIT_FAILURE );
996 			}
997 
998 			if ( ber_flatten( syncber, &syncbvalp ) == -1 ) {
999 				tool_exit( ld, EXIT_FAILURE );
1000 			}
1001 
1002 			c[i].ldctl_oid = LDAP_CONTROL_SYNC;
1003 			c[i].ldctl_value = (*syncbvalp);
1004 			c[i].ldctl_iscritical = ldapsync < 0;
1005 			i++;
1006 		}
1007 
1008 		if ( valuesReturnFilter ) {
1009 			if ( ctrl_add() ) {
1010 				tool_exit( ld, EXIT_FAILURE );
1011 			}
1012 
1013 			if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
1014 				tool_exit( ld, EXIT_FAILURE );
1015 			}
1016 
1017 			if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) {
1018 				ber_free( vrber, 1 );
1019 				fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter );
1020 				tool_exit( ld, EXIT_FAILURE );
1021 			}
1022 
1023 			if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) {
1024 				tool_exit( ld, EXIT_FAILURE );
1025 			}
1026 
1027 			c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
1028 			c[i].ldctl_iscritical = valuesReturnFilter > 1;
1029 			i++;
1030 		}
1031 
1032 		if ( pagedResults ) {
1033 			if ( ctrl_add() ) {
1034 				tool_exit( ld, EXIT_FAILURE );
1035 			}
1036 
1037 			if ( ldap_create_page_control_value( ld,
1038 				pageSize, &pr_cookie, &c[i].ldctl_value ) )
1039 			{
1040 				tool_exit( ld, EXIT_FAILURE );
1041 			}
1042 
1043 			if ( pr_cookie.bv_val != NULL ) {
1044 				ber_memfree( pr_cookie.bv_val );
1045 				pr_cookie.bv_val = NULL;
1046 				pr_cookie.bv_len = 0;
1047 			}
1048 
1049 			c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
1050 			c[i].ldctl_iscritical = pagedResults > 1;
1051 			i++;
1052 		}
1053 
1054 		if ( sss ) {
1055 			if ( ctrl_add() ) {
1056 				tool_exit( ld, EXIT_FAILURE );
1057 			}
1058 
1059 			if ( ldap_create_sort_control_value( ld,
1060 				sss_keys, &c[i].ldctl_value ) )
1061 			{
1062 				tool_exit( ld, EXIT_FAILURE );
1063 			}
1064 
1065 			c[i].ldctl_oid = LDAP_CONTROL_SORTREQUEST;
1066 			c[i].ldctl_iscritical = sss > 1;
1067 			i++;
1068 		}
1069 
1070 		if ( vlv ) {
1071 			if ( ctrl_add() ) {
1072 				tool_exit( ld, EXIT_FAILURE );
1073 			}
1074 
1075 			if ( ldap_create_vlv_control_value( ld,
1076 				&vlvInfo, &c[i].ldctl_value ) )
1077 			{
1078 				tool_exit( ld, EXIT_FAILURE );
1079 			}
1080 
1081 			c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
1082 			c[i].ldctl_iscritical = sss > 1;
1083 			i++;
1084 		}
1085 #ifdef LDAP_CONTROL_X_DEREF
1086 		if ( derefcrit ) {
1087 			if ( derefval.bv_val == NULL ) {
1088 				int i;
1089 
1090 				assert( ds != NULL );
1091 
1092 				if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
1093 					tool_exit( ld, EXIT_FAILURE );
1094 				}
1095 
1096 				for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) {
1097 					ldap_memfree( ds[ i ].derefAttr );
1098 					ldap_charray_free( ds[ i ].attributes );
1099 				}
1100 				ldap_memfree( ds );
1101 				ds = NULL;
1102 			}
1103 
1104 			if ( ctrl_add() ) {
1105 				tool_exit( ld, EXIT_FAILURE );
1106 			}
1107 
1108 			c[ i ].ldctl_iscritical = derefcrit > 1;
1109 			c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF;
1110 			c[ i ].ldctl_value = derefval;
1111 			i++;
1112 		}
1113 #endif /* LDAP_CONTROL_X_DEREF */
1114 	}
1115 
1116 	tool_server_controls( ld, c, i );
1117 
1118 	if ( seber ) ber_free( seber, 1 );
1119 	if ( vrber ) ber_free( vrber, 1 );
1120 
1121 	/* step back to the original number of controls, so that
1122 	 * those set while parsing args are preserved */
1123 	nctrls = save_nctrls;
1124 
1125 	if ( verbose ) {
1126 		fprintf( stderr, _("filter%s: %s\nrequesting: "),
1127 			infile != NULL ? _(" pattern") : "",
1128 			filtpattern );
1129 
1130 		if ( attrs == NULL ) {
1131 			fprintf( stderr, _("All userApplication attributes") );
1132 		} else {
1133 			for ( i = 0; attrs[ i ] != NULL; ++i ) {
1134 				fprintf( stderr, "%s ", attrs[ i ] );
1135 			}
1136 		}
1137 		fprintf( stderr, "\n" );
1138 	}
1139 
1140 	if ( ldif == 0 ) {
1141 		printf( _("# extended LDIF\n") );
1142 	} else if ( ldif < 3 ) {
1143 		printf( _("version: %d\n\n"), 1 );
1144 	}
1145 
1146 	if (ldif < 2 ) {
1147 		char	*realbase = base;
1148 
1149 		if ( realbase == NULL ) {
1150 			ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase );
1151 		}
1152 
1153 		printf( "#\n" );
1154 		printf(_("# LDAPv%d\n"), protocol);
1155 		printf(_("# base <%s>%s with scope %s\n"),
1156 			realbase ? realbase : "",
1157 			( realbase == NULL || realbase != base ) ? " (default)" : "",
1158 			((scope == LDAP_SCOPE_BASE) ? "baseObject"
1159 				: ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
1160 				: ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
1161 				: "subtree" ))));
1162 		printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "",
1163 		       filtpattern);
1164 		printf(_("# requesting: "));
1165 
1166 		if ( attrs == NULL ) {
1167 			printf( _("ALL") );
1168 		} else {
1169 			for ( i = 0; attrs[ i ] != NULL; ++i ) {
1170 				printf( "%s ", attrs[ i ] );
1171 			}
1172 		}
1173 
1174 		if ( manageDSAit ) {
1175 			printf(_("\n# with manageDSAit %scontrol"),
1176 				manageDSAit > 1 ? _("critical ") : "" );
1177 		}
1178 		if ( noop ) {
1179 			printf(_("\n# with noop %scontrol"),
1180 				noop > 1 ? _("critical ") : "" );
1181 		}
1182 		if ( subentries ) {
1183 			printf(_("\n# with subentries %scontrol: %s"),
1184 				subentries < 0 ? _("critical ") : "",
1185 				abs(subentries) == 1 ? "false" : "true" );
1186 		}
1187 		if ( valuesReturnFilter ) {
1188 			printf(_("\n# with valuesReturnFilter %scontrol: %s"),
1189 				valuesReturnFilter > 1 ? _("critical ") : "", vrFilter );
1190 		}
1191 		if ( pagedResults ) {
1192 			printf(_("\n# with pagedResults %scontrol: size=%d"),
1193 				(pagedResults > 1) ? _("critical ") : "",
1194 				pageSize );
1195 		}
1196 		if ( sss ) {
1197 			printf(_("\n# with server side sorting %scontrol"),
1198 				sss > 1 ? _("critical ") : "" );
1199 		}
1200 		if ( vlv ) {
1201 			printf(_("\n# with virtual list view %scontrol: %d/%d"),
1202 				vlv > 1 ? _("critical ") : "",
1203 				vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count);
1204 			if ( vlvInfo.ldvlv_attrvalue )
1205 				printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val );
1206 			else
1207 				printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count );
1208 		}
1209 #ifdef LDAP_CONTROL_X_DEREF
1210 		if ( derefcrit ) {
1211 			printf(_("\n# with dereference %scontrol"),
1212 				derefcrit > 1 ? _("critical ") : "" );
1213 		}
1214 #endif
1215 
1216 		printf( _("\n#\n\n") );
1217 
1218 		if ( realbase && realbase != base ) {
1219 			ldap_memfree( realbase );
1220 		}
1221 	}
1222 
1223 	if ( infile == NULL ) {
1224 		rc = dosearch( ld, base, scope, NULL, filtpattern,
1225 			attrs, attrsonly, NULL, NULL, NULL, sizelimit );
1226 
1227 	} else {
1228 		rc = 0;
1229 		first = 1;
1230 		while ( fgets( line, sizeof( line ), fp ) != NULL ) {
1231 			line[ strlen( line ) - 1 ] = '\0';
1232 			if ( !first ) {
1233 				putchar( '\n' );
1234 			} else {
1235 				first = 0;
1236 			}
1237 			rc1 = dosearch( ld, base, scope, filtpattern, line,
1238 				attrs, attrsonly, NULL, NULL, NULL, sizelimit );
1239 
1240 			if ( rc1 != 0 ) {
1241 				rc = rc1;
1242 				if ( !contoper )
1243 					break;
1244 			}
1245 		}
1246 		if ( fp != stdin ) {
1247 			fclose( fp );
1248 			fp = NULL;
1249 		}
1250 	}
1251 
1252 	if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) {
1253 		char	buf[12];
1254 		int	i, moreEntries, tmpSize;
1255 
1256 		/* Loop to get the next pages when
1257 		 * enter is pressed on the terminal.
1258 		 */
1259 		if ( pagePrompt != 0 ) {
1260 			if ( entriesLeft > 0 ) {
1261 				printf( _("Estimate entries: %d\n"), entriesLeft );
1262 			}
1263 			printf( _("Press [size] Enter for the next {%d|size} entries.\n"),
1264 				(int)pageSize );
1265 			i = 0;
1266 			moreEntries = getchar();
1267 			while ( moreEntries != EOF && moreEntries != '\n' ) {
1268 				if ( i < (int)sizeof(buf) - 1 ) {
1269 					buf[i] = moreEntries;
1270 					i++;
1271 				}
1272 				moreEntries = getchar();
1273 			}
1274 			buf[i] = '\0';
1275 
1276 			if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) {
1277 				int num = sscanf( buf, "%d", &tmpSize );
1278 				if ( num != 1 ) {
1279 					fprintf( stderr,
1280 						_("Invalid value for PagedResultsControl, %s.\n"), buf);
1281 					tool_exit( ld, EXIT_FAILURE );
1282 
1283 				}
1284 				pageSize = (ber_int_t)tmpSize;
1285 			}
1286 		}
1287 
1288 		goto getNextPage;
1289 	}
1290 
1291 	if (( rc == LDAP_SUCCESS ) && vlv ) {
1292 		char	buf[BUFSIZ];
1293 		int	i, moreEntries;
1294 
1295 		/* Loop to get the next window when
1296 		 * enter is pressed on the terminal.
1297 		 */
1298 		printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n"));
1299 		i = 0;
1300 		moreEntries = getchar();
1301 		while ( moreEntries != EOF && moreEntries != '\n' ) {
1302 			if ( i < (int)sizeof(buf) - 1 ) {
1303 				buf[i] = moreEntries;
1304 				i++;
1305 			}
1306 			moreEntries = getchar();
1307 		}
1308 		buf[i] = '\0';
1309 		if ( buf[0] ) {
1310 			i = parse_vlv( strdup( buf ));
1311 			if ( i )
1312 				tool_exit( ld, EXIT_FAILURE );
1313 		} else {
1314 			vlvInfo.ldvlv_attrvalue = NULL;
1315 			vlvInfo.ldvlv_count = vlvCount;
1316 			vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count;
1317 		}
1318 
1319 		if ( vlvInfo.ldvlv_context )
1320 			ber_bvfree( vlvInfo.ldvlv_context );
1321 		vlvInfo.ldvlv_context = vlvContext;
1322 
1323 		goto getNextPage;
1324 	}
1325 
1326 	if ( base != NULL ) {
1327 		ber_memfree( base );
1328 	}
1329 	if ( control != NULL ) {
1330 		ber_memfree( control );
1331 	}
1332 	if ( sss_keys != NULL ) {
1333 		ldap_free_sort_keylist( sss_keys );
1334 	}
1335 	if ( derefval.bv_val != NULL ) {
1336 		ldap_memfree( derefval.bv_val );
1337 	}
1338 	if ( urlpre != NULL ) {
1339 		if ( def_urlpre != urlpre )
1340 			free( def_urlpre );
1341 		free( urlpre );
1342 	}
1343 
1344 	if ( c ) {
1345 		for ( ; save_nctrls-- > 0; ) {
1346 			ber_memfree( c[ save_nctrls ].ldctl_value.bv_val );
1347 		}
1348 		free( c );
1349 		c = NULL;
1350 	}
1351 
1352 	tool_exit( ld, rc );
1353 }
1354 
1355 
1356 static int dosearch(
1357 	LDAP	*ld,
1358 	char	*base,
1359 	int		scope,
1360 	char	*filtpatt,
1361 	char	*value,
1362 	char	**attrs,
1363 	int		attrsonly,
1364 	LDAPControl **sctrls,
1365 	LDAPControl **cctrls,
1366 	struct timeval *timeout,
1367 	int sizelimit )
1368 {
1369 	char			*filter;
1370 	int			rc, rc2 = LDAP_OTHER;
1371 	int			nresponses;
1372 	int			nentries;
1373 	int			nreferences;
1374 	int			nextended;
1375 	int			npartial;
1376 	LDAPMessage		*res, *msg;
1377 	ber_int_t		msgid;
1378 	char			*retoid = NULL;
1379 	struct berval		*retdata = NULL;
1380 	int			nresponses_psearch = -1;
1381 	int			cancel_msgid = -1;
1382 	struct timeval tv, *tvp = NULL;
1383 	struct timeval tv_timelimit, *tv_timelimitp = NULL;
1384 
1385 	if( filtpatt != NULL ) {
1386 		size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1, outlen;
1387 		filter = malloc( max_fsize );
1388 		if( filter == NULL ) {
1389 			perror( "malloc" );
1390 			return EXIT_FAILURE;
1391 		}
1392 
1393 		outlen = snprintf( filter, max_fsize, filtpatt, value );
1394 		if( outlen >= max_fsize ) {
1395 			fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt );
1396 			free( filter );
1397 			return EXIT_FAILURE;
1398 		}
1399 
1400 		if ( verbose ) {
1401 			fprintf( stderr, _("filter: %s\n"), filter );
1402 		}
1403 
1404 		if( ldif < 2 ) {
1405 			printf( _("#\n# filter: %s\n#\n"), filter );
1406 		}
1407 
1408 	} else {
1409 		filter = value;
1410 	}
1411 
1412 	if ( dont ) {
1413 		if ( filtpatt != NULL ) {
1414 			free( filter );
1415 		}
1416 		return LDAP_SUCCESS;
1417 	}
1418 
1419 	if ( timelimit > 0 ) {
1420 		tv_timelimit.tv_sec = timelimit;
1421 		tv_timelimit.tv_usec = 0;
1422 		tv_timelimitp = &tv_timelimit;
1423 	}
1424 
1425 	rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
1426 		sctrls, cctrls, tv_timelimitp, sizelimit, &msgid );
1427 
1428 	if ( filtpatt != NULL ) {
1429 		free( filter );
1430 	}
1431 
1432 	if( rc != LDAP_SUCCESS ) {
1433 		tool_perror( "ldap_search_ext", rc, NULL, NULL, NULL, NULL );
1434 		return( rc );
1435 	}
1436 
1437 	nresponses = nentries = nreferences = nextended = npartial = 0;
1438 
1439 	res = NULL;
1440 
1441 	if ( timelimit > 0 ) {
1442 		/* disable timeout */
1443 		tv.tv_sec = -1;
1444 		tv.tv_usec = 0;
1445 		tvp = &tv;
1446 	}
1447 
1448 	while ((rc = ldap_result( ld, LDAP_RES_ANY,
1449 		sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE,
1450 		tvp, &res )) > 0 )
1451 	{
1452 		if ( tool_check_abandon( ld, msgid ) ) {
1453 			return -1;
1454 		}
1455 
1456 		if( sortattr ) {
1457 			(void) ldap_sort_entries( ld, &res,
1458 				( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
1459 		}
1460 
1461 		for ( msg = ldap_first_message( ld, res );
1462 			msg != NULL;
1463 			msg = ldap_next_message( ld, msg ) )
1464 		{
1465 			if ( nresponses++ ) putchar('\n');
1466 			if ( nresponses_psearch >= 0 )
1467 				nresponses_psearch++;
1468 
1469 			switch( ldap_msgtype( msg ) ) {
1470 			case LDAP_RES_SEARCH_ENTRY:
1471 				nentries++;
1472 				print_entry( ld, msg, attrsonly );
1473 				break;
1474 
1475 			case LDAP_RES_SEARCH_REFERENCE:
1476 				nreferences++;
1477 				print_reference( ld, msg );
1478 				break;
1479 
1480 			case LDAP_RES_EXTENDED:
1481 				nextended++;
1482 				print_extended( ld, msg );
1483 
1484 				if ( ldap_msgid( msg ) == 0 ) {
1485 					/* unsolicited extended operation */
1486 					goto done;
1487 				}
1488 
1489 				if ( cancel_msgid != -1 &&
1490 						cancel_msgid == ldap_msgid( msg ) ) {
1491 					printf(_("Cancelled \n"));
1492 					printf(_("cancel_msgid = %d\n"), cancel_msgid);
1493 					goto done;
1494 				}
1495 				break;
1496 
1497 			case LDAP_RES_SEARCH_RESULT:
1498 				/* pagedResults stuff is dealt with
1499 				 * in tool_print_ctrls(), called by
1500 				 * print_results(). */
1501 				rc2 = print_result( ld, msg, 1 );
1502 				if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
1503 					break;
1504 				}
1505 
1506 				goto done;
1507 
1508 			case LDAP_RES_INTERMEDIATE:
1509 				npartial++;
1510 				ldap_parse_intermediate( ld, msg,
1511 					&retoid, &retdata, NULL, 0 );
1512 
1513 				nresponses_psearch = 0;
1514 
1515 				if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) {
1516 					printf(_("SyncInfo Received\n"));
1517 					ldap_memfree( retoid );
1518 					ber_bvfree( retdata );
1519 					break;
1520 				}
1521 
1522 				print_partial( ld, msg );
1523 				ldap_memfree( retoid );
1524 				ber_bvfree( retdata );
1525 				goto done;
1526 			}
1527 
1528 			if ( ldapsync && sync_slimit != -1 &&
1529 					nresponses_psearch >= sync_slimit ) {
1530 				BerElement *msgidber = NULL;
1531 				struct berval *msgidvalp = NULL;
1532 				msgidber = ber_alloc_t(LBER_USE_DER);
1533 				ber_printf(msgidber, "{i}", msgid);
1534 				ber_flatten(msgidber, &msgidvalp);
1535 				ldap_extended_operation(ld, LDAP_EXOP_CANCEL,
1536 					msgidvalp, NULL, NULL, &cancel_msgid);
1537 				nresponses_psearch = -1;
1538 			}
1539 		}
1540 
1541 		ldap_msgfree( res );
1542 	}
1543 
1544 done:
1545 	if ( tvp == NULL && rc != LDAP_RES_SEARCH_RESULT ) {
1546 		ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&rc2 );
1547 	}
1548 
1549 	ldap_msgfree( res );
1550 
1551 	if ( pagedResults ) {
1552 		npagedresponses += nresponses;
1553 		npagedentries += nentries;
1554 		npagedextended += nextended;
1555 		npagedpartial += npartial;
1556 		npagedreferences += nreferences;
1557 		if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) {
1558 			printf( _("\n# numResponses: %d\n"), npagedresponses );
1559 			if( npagedentries ) {
1560 				printf( _("# numEntries: %d\n"), npagedentries );
1561 			}
1562 			if( npagedextended ) {
1563 				printf( _("# numExtended: %d\n"), npagedextended );
1564 			}
1565 			if( npagedpartial ) {
1566 				printf( _("# numPartial: %d\n"), npagedpartial );
1567 			}
1568 			if( npagedreferences ) {
1569 				printf( _("# numReferences: %d\n"), npagedreferences );
1570 			}
1571 		}
1572 	} else if ( ldif < 2 ) {
1573 		printf( _("\n# numResponses: %d\n"), nresponses );
1574 		if( nentries ) printf( _("# numEntries: %d\n"), nentries );
1575 		if( nextended ) printf( _("# numExtended: %d\n"), nextended );
1576 		if( npartial ) printf( _("# numPartial: %d\n"), npartial );
1577 		if( nreferences ) printf( _("# numReferences: %d\n"), nreferences );
1578 	}
1579 
1580 	if ( rc != LDAP_RES_SEARCH_RESULT ) {
1581 		tool_perror( "ldap_result", rc2, NULL, NULL, NULL, NULL );
1582 	}
1583 
1584 	return( rc2 );
1585 }
1586 
1587 /* This is the proposed new way of doing things.
1588  * It is more efficient, but the API is non-standard.
1589  */
1590 static void
1591 print_entry(
1592 	LDAP	*ld,
1593 	LDAPMessage	*entry,
1594 	int		attrsonly)
1595 {
1596 	char		*ufn = NULL;
1597 	char	tmpfname[ 256 ];
1598 	char	url[ 256 ];
1599 	int			i, rc;
1600 	BerElement		*ber = NULL;
1601 	struct berval		bv, *bvals, **bvp = &bvals;
1602 	LDAPControl **ctrls = NULL;
1603 	FILE		*tmpfp;
1604 
1605 	rc = ldap_get_dn_ber( ld, entry, &ber, &bv );
1606 
1607 	if ( ldif < 2 ) {
1608 		ufn = ldap_dn2ufn( bv.bv_val );
1609 		tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 );
1610 	}
1611 	tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
1612 
1613 	rc = ldap_get_entry_controls( ld, entry, &ctrls );
1614 	if( rc != LDAP_SUCCESS ) {
1615 		fprintf(stderr, _("print_entry: %d\n"), rc );
1616 		tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL );
1617 		tool_exit( ld, EXIT_FAILURE );
1618 	}
1619 
1620 	if( ctrls ) {
1621 		tool_print_ctrls( ld, ctrls );
1622 		ldap_controls_free( ctrls );
1623 	}
1624 
1625 	if ( includeufn ) {
1626 		if( ufn == NULL ) {
1627 			ufn = ldap_dn2ufn( bv.bv_val );
1628 		}
1629 		tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 );
1630 	}
1631 
1632 	if( ufn != NULL ) ldap_memfree( ufn );
1633 
1634 	if ( attrsonly ) bvp = NULL;
1635 
1636 	for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp );
1637 		rc == LDAP_SUCCESS;
1638 		rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) )
1639 	{
1640 		if (bv.bv_val == NULL) break;
1641 
1642 		if ( attrsonly ) {
1643 			tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 );
1644 
1645 		} else if ( bvals ) {
1646 			for ( i = 0; bvals[i].bv_val != NULL; i++ ) {
1647 				if ( vals2tmp > 1 || ( vals2tmp &&
1648 					ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len )))
1649 				{
1650 					int tmpfd;
1651 					/* write value to file */
1652 					snprintf( tmpfname, sizeof tmpfname,
1653 						"%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
1654 						tmpdir, bv.bv_val );
1655 					tmpfp = NULL;
1656 
1657 					tmpfd = mkstemp( tmpfname );
1658 
1659 					if ( tmpfd < 0  ) {
1660 						perror( tmpfname );
1661 						continue;
1662 					}
1663 
1664 					if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) {
1665 						perror( tmpfname );
1666 						continue;
1667 					}
1668 
1669 					if ( fwrite( bvals[ i ].bv_val,
1670 						bvals[ i ].bv_len, 1, tmpfp ) == 0 )
1671 					{
1672 						perror( tmpfname );
1673 						fclose( tmpfp );
1674 						continue;
1675 					}
1676 
1677 					fclose( tmpfp );
1678 
1679 					snprintf( url, sizeof url, "%s%s", urlpre,
1680 						&tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
1681 
1682 					urlize( url );
1683 					tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url ));
1684 
1685 				} else {
1686 					tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val,
1687 						bvals[ i ].bv_val, bvals[ i ].bv_len );
1688 				}
1689 			}
1690 			ber_memfree( bvals );
1691 		}
1692 	}
1693 
1694 	if( ber != NULL ) {
1695 		ber_free( ber, 0 );
1696 	}
1697 }
1698 
1699 static void print_reference(
1700 	LDAP *ld,
1701 	LDAPMessage *reference )
1702 {
1703 	int rc;
1704 	char **refs = NULL;
1705 	LDAPControl **ctrls;
1706 
1707 	if( ldif < 2 ) {
1708 		printf(_("# search reference\n"));
1709 	}
1710 
1711 	rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 );
1712 
1713 	if( rc != LDAP_SUCCESS ) {
1714 		tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL );
1715 		tool_exit( ld, EXIT_FAILURE );
1716 	}
1717 
1718 	if( refs ) {
1719 		int i;
1720 		for( i=0; refs[i] != NULL; i++ ) {
1721 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
1722 				"ref", refs[i], strlen(refs[i]) );
1723 		}
1724 		ber_memvfree( (void **) refs );
1725 	}
1726 
1727 	if( ctrls ) {
1728 		tool_print_ctrls( ld, ctrls );
1729 		ldap_controls_free( ctrls );
1730 	}
1731 }
1732 
1733 static void print_extended(
1734 	LDAP *ld,
1735 	LDAPMessage *extended )
1736 {
1737 	int rc;
1738 	char *retoid = NULL;
1739 	struct berval *retdata = NULL;
1740 
1741 	if( ldif < 2 ) {
1742 		printf(_("# extended result response\n"));
1743 	}
1744 
1745 	rc = ldap_parse_extended_result( ld, extended,
1746 		&retoid, &retdata, 0 );
1747 
1748 	if( rc != LDAP_SUCCESS ) {
1749 		tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
1750 		tool_exit( ld, EXIT_FAILURE );
1751 	}
1752 
1753 	if ( ldif < 2 ) {
1754 		tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
1755 			"extended", retoid, retoid ? strlen(retoid) : 0 );
1756 	}
1757 	ber_memfree( retoid );
1758 
1759 	if(retdata) {
1760 		if ( ldif < 2 ) {
1761 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
1762 				"data", retdata->bv_val, retdata->bv_len );
1763 		}
1764 		ber_bvfree( retdata );
1765 	}
1766 
1767 	print_result( ld, extended, 0 );
1768 }
1769 
1770 static void print_partial(
1771 	LDAP *ld,
1772 	LDAPMessage *partial )
1773 {
1774 	int rc;
1775 	char *retoid = NULL;
1776 	struct berval *retdata = NULL;
1777 	LDAPControl **ctrls = NULL;
1778 
1779 	if( ldif < 2 ) {
1780 		printf(_("# extended partial response\n"));
1781 	}
1782 
1783 	rc = ldap_parse_intermediate( ld, partial,
1784 		&retoid, &retdata, &ctrls, 0 );
1785 
1786 	if( rc != LDAP_SUCCESS ) {
1787 		tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL );
1788 		tool_exit( ld, EXIT_FAILURE );
1789 	}
1790 
1791 	if ( ldif < 2 ) {
1792 		tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
1793 			"partial", retoid, retoid ? strlen(retoid) : 0 );
1794 	}
1795 
1796 	ber_memfree( retoid );
1797 
1798 	if( retdata ) {
1799 		if ( ldif < 2 ) {
1800 			tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
1801 				"data", retdata->bv_val, retdata->bv_len );
1802 		}
1803 
1804 		ber_bvfree( retdata );
1805 	}
1806 
1807 	if( ctrls ) {
1808 		tool_print_ctrls( ld, ctrls );
1809 		ldap_controls_free( ctrls );
1810 	}
1811 }
1812 
1813 static int print_result(
1814 	LDAP *ld,
1815 	LDAPMessage *result, int search )
1816 {
1817 	int rc;
1818 	int err;
1819 	char *matcheddn = NULL;
1820 	char *text = NULL;
1821 	char **refs = NULL;
1822 	LDAPControl **ctrls = NULL;
1823 
1824 	if( search ) {
1825 		if ( ldif < 2 ) {
1826 			printf(_("# search result\n"));
1827 		}
1828 		if ( ldif < 1 ) {
1829 			printf("%s: %d\n", _("search"), ldap_msgid(result) );
1830 		}
1831 	}
1832 
1833 	rc = ldap_parse_result( ld, result,
1834 		&err, &matcheddn, &text, &refs, &ctrls, 0 );
1835 
1836 	if( rc != LDAP_SUCCESS ) {
1837 		tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
1838 		tool_exit( ld, EXIT_FAILURE );
1839 	}
1840 
1841 
1842 	if( !ldif ) {
1843 		printf( _("result: %d %s\n"), err, ldap_err2string(err) );
1844 
1845 	} else if ( err != LDAP_SUCCESS ) {
1846 		fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err );
1847 	}
1848 
1849 	if( matcheddn ) {
1850 		if( *matcheddn ) {
1851 		if( !ldif ) {
1852 			tool_write_ldif( LDIF_PUT_VALUE,
1853 				"matchedDN", matcheddn, strlen(matcheddn) );
1854 		} else {
1855 			fprintf( stderr, _("Matched DN: %s\n"), matcheddn );
1856 		}
1857 		}
1858 
1859 		ber_memfree( matcheddn );
1860 	}
1861 
1862 	if( text ) {
1863 		if( *text ) {
1864 			if( !ldif ) {
1865 				if ( err == LDAP_PARTIAL_RESULTS ) {
1866 					char	*line;
1867 
1868 					for ( line = text; line != NULL; ) {
1869 						char	*next = strchr( line, '\n' );
1870 
1871 						tool_write_ldif( LDIF_PUT_TEXT,
1872 							"text", line,
1873 							next ? (size_t) (next - line) : strlen( line ));
1874 
1875 						line = next ? next + 1 : NULL;
1876 					}
1877 
1878 				} else {
1879 					tool_write_ldif( LDIF_PUT_TEXT, "text",
1880 						text, strlen(text) );
1881 				}
1882 			} else {
1883 				fprintf( stderr, _("Additional information: %s\n"), text );
1884 			}
1885 		}
1886 
1887 		ber_memfree( text );
1888 	}
1889 
1890 	if( refs ) {
1891 		int i;
1892 		for( i=0; refs[i] != NULL; i++ ) {
1893 			if( !ldif ) {
1894 				tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) );
1895 			} else {
1896 				fprintf( stderr, _("Referral: %s\n"), refs[i] );
1897 			}
1898 		}
1899 
1900 		ber_memvfree( (void **) refs );
1901 	}
1902 
1903 	pr_morePagedResults = 0;
1904 
1905 	if( ctrls ) {
1906 		tool_print_ctrls( ld, ctrls );
1907 		ldap_controls_free( ctrls );
1908 	}
1909 
1910 	return err;
1911 }
1912