Back to index

openldap  2.4.31
ldapsearch.c
Go to the documentation of this file.
00001 /* ldapsearch -- a tool for searching LDAP directories */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
00007  * Portions Copyright 1998-2001 Net Boolean Incorporated.
00008  * Portions Copyright 2001-2003 IBM Corporation.
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted only as authorized by the OpenLDAP
00013  * Public License.
00014  *
00015  * A copy of this license is available in the file LICENSE in the
00016  * top-level directory of the distribution or, alternatively, at
00017  * <http://www.OpenLDAP.org/license.html>.
00018  */
00019 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
00020  * All rights reserved.
00021  *
00022  * Redistribution and use in source and binary forms are permitted
00023  * provided that this notice is preserved and that due credit is given
00024  * to the University of Michigan at Ann Arbor.  The name of the
00025  * University may not be used to endorse or promote products derived
00026  * from this software without specific prior written permission.  This
00027  * software is provided ``as is'' without express or implied warranty.
00028  */
00029 /* ACKNOWLEDGEMENTS:
00030  * This work was originally developed by the University of Michigan
00031  * (as part of U-MICH LDAP).  Additional significant contributors
00032  * include:
00033  *   Jong Hyuk Choi
00034  *   Lynn Moss
00035  *   Mikhail Sahalaev
00036  *   Kurt D. Zeilenga
00037  */
00038 
00039 #include "portable.h"
00040 
00041 #include <stdio.h>
00042 
00043 #include <ac/stdlib.h>
00044 #include <ac/ctype.h>
00045 #include <ac/string.h>
00046 #include <ac/unistd.h>
00047 #include <ac/errno.h>
00048 #include <ac/time.h>
00049 
00050 #include <sys/stat.h>
00051 
00052 #include <ac/signal.h>
00053 
00054 #ifdef HAVE_FCNTL_H
00055 #include <fcntl.h>
00056 #endif
00057 #ifdef HAVE_SYS_TYPES_H
00058 #include <sys/types.h>
00059 #endif
00060 #ifdef HAVE_IO_H
00061 #include <io.h>
00062 #endif
00063 
00064 #include <ldap.h>
00065 
00066 #include "ldif.h"
00067 #include "lutil.h"
00068 #include "lutil_ldap.h"
00069 #include "ldap_defaults.h"
00070 #include "ldap_pvt.h"
00071 
00072 #include "common.h"
00073 
00074 #if !LDAP_DEPRECATED
00075 /*
00076  * NOTE: we use this deprecated function only because
00077  * we want ldapsearch to provide some client-side sorting 
00078  * capability.
00079  */
00080 /* from ldap.h */
00081 typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */
00082        LDAP_CONST char *left,
00083        LDAP_CONST char *right ));
00084 
00085 LDAP_F( int ) /* deprecated */
00086 ldap_sort_entries LDAP_P(( LDAP *ld,
00087        LDAPMessage **chain,
00088        LDAP_CONST char *attr,
00089        LDAP_SORT_AD_CMP_PROC *cmp ));
00090 #endif
00091 
00092 static int scope = LDAP_SCOPE_SUBTREE;
00093 static int deref = -1;
00094 static int attrsonly;
00095 static int timelimit = -1;
00096 static int sizelimit = -1;
00097 
00098 static char *control;
00099 
00100 static char *def_tmpdir;
00101 static char *def_urlpre;
00102 
00103 #if defined(__CYGWIN__) || defined(__MINGW32__)
00104 /* Turn off commandline globbing, otherwise you cannot search for
00105  * attribute '*'
00106  */
00107 int _CRT_glob = 0;
00108 #endif
00109 
00110 void
00111 usage( void )
00112 {
00113        fprintf( stderr, _("usage: %s [options] [filter [attributes...]]\nwhere:\n"), prog);
00114        fprintf( stderr, _("  filter\tRFC 4515 compliant LDAP search filter\n"));
00115        fprintf( stderr, _("  attributes\twhitespace-separated list of attribute descriptions\n"));
00116        fprintf( stderr, _("    which may include:\n"));
00117        fprintf( stderr, _("      1.1   no attributes\n"));
00118        fprintf( stderr, _("      *     all user attributes\n"));
00119        fprintf( stderr, _("      +     all operational attributes\n"));
00120 
00121 
00122        fprintf( stderr, _("Search options:\n"));
00123        fprintf( stderr, _("  -a deref   one of never (default), always, search, or find\n"));
00124        fprintf( stderr, _("  -A         retrieve attribute names only (no values)\n"));
00125        fprintf( stderr, _("  -b basedn  base dn for search\n"));
00126        fprintf( stderr, _("  -c         continuous operation mode (do not stop on errors)\n"));
00127        fprintf( stderr, _("  -E [!]<ext>[=<extparam>] search extensions (! indicates criticality)\n"));
00128        fprintf( stderr, _("             [!]domainScope              (domain scope)\n"));
00129        fprintf( stderr, _("             !dontUseCopy                (Don't Use Copy)\n"));
00130        fprintf( stderr, _("             [!]mv=<filter>              (RFC 3876 matched values filter)\n"));
00131        fprintf( stderr, _("             [!]pr=<size>[/prompt|noprompt] (RFC 2696 paged results/prompt)\n"));
00132        fprintf( stderr, _("             [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]\n"));
00133        fprintf( stderr, _("                                         (RFC 2891 server side sorting)\n"));
00134        fprintf( stderr, _("             [!]subentries[=true|false]  (RFC 3672 subentries)\n"));
00135        fprintf( stderr, _("             [!]sync=ro[/<cookie>]       (RFC 4533 LDAP Sync refreshOnly)\n"));
00136        fprintf( stderr, _("                     rp[/<cookie>][/<slimit>] (refreshAndPersist)\n"));
00137        fprintf( stderr, _("             [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n"));
00138        fprintf( stderr, _("                                         (ldapv3-vlv-09 virtual list views)\n"));
00139 #ifdef LDAP_CONTROL_X_DEREF
00140        fprintf( stderr, _("             [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
00141 #endif
00142        fprintf( stderr, _("             [!]<oid>[=:<b64value>] (generic control; no response handling)\n"));
00143        fprintf( stderr, _("  -f file    read operations from `file'\n"));
00144        fprintf( stderr, _("  -F prefix  URL prefix for files (default: %s)\n"), def_urlpre);
00145        fprintf( stderr, _("  -l limit   time limit (in seconds, or \"none\" or \"max\") for search\n"));
00146        fprintf( stderr, _("  -L         print responses in LDIFv1 format\n"));
00147        fprintf( stderr, _("  -LL        print responses in LDIF format without comments\n"));
00148        fprintf( stderr, _("  -LLL       print responses in LDIF format without comments\n"));
00149        fprintf( stderr, _("             and version\n"));
00150        fprintf( stderr, _("  -M         enable Manage DSA IT control (-MM to make critical)\n"));
00151        fprintf( stderr, _("  -P version protocol version (default: 3)\n"));
00152        fprintf( stderr, _("  -s scope   one of base, one, sub or children (search scope)\n"));
00153        fprintf( stderr, _("  -S attr    sort the results by attribute `attr'\n"));
00154        fprintf( stderr, _("  -t         write binary values to files in temporary directory\n"));
00155        fprintf( stderr, _("  -tt        write all values to files in temporary directory\n"));
00156        fprintf( stderr, _("  -T path    write files to directory specified by path (default: %s)\n"), def_tmpdir);
00157        fprintf( stderr, _("  -u         include User Friendly entry names in the output\n"));
00158        fprintf( stderr, _("  -z limit   size limit (in entries, or \"none\" or \"max\") for search\n"));
00159        tool_common_usage();
00160        exit( EXIT_FAILURE );
00161 }
00162 
00163 static void print_entry LDAP_P((
00164        LDAP   *ld,
00165        LDAPMessage   *entry,
00166        int           attrsonly));
00167 
00168 static void print_reference(
00169        LDAP *ld,
00170        LDAPMessage *reference );
00171 
00172 static void print_extended(
00173        LDAP *ld,
00174        LDAPMessage *extended );
00175 
00176 static void print_partial(
00177        LDAP *ld,
00178        LDAPMessage *partial );
00179 
00180 static int print_result(
00181        LDAP *ld,
00182        LDAPMessage *result,
00183        int search );
00184 
00185 static int dosearch LDAP_P((
00186        LDAP   *ld,
00187        char   *base,
00188        int           scope,
00189        char   *filtpatt,
00190        char   *value,
00191        char   **attrs,
00192        int           attrsonly,
00193        LDAPControl **sctrls,
00194        LDAPControl **cctrls,
00195        struct timeval *timeout,
00196        int    sizelimit ));
00197 
00198 static char *tmpdir = NULL;
00199 static char *urlpre = NULL;
00200 static char   *base = NULL;
00201 static char   *sortattr = NULL;
00202 static int  includeufn, vals2tmp = 0;
00203 
00204 static int subentries = 0, valuesReturnFilter = 0;
00205 static char   *vrFilter = NULL;
00206 
00207 #ifdef LDAP_CONTROL_DONTUSECOPY
00208 static int dontUseCopy = 0;
00209 #endif
00210 
00211 static int domainScope = 0;
00212 
00213 static int sss = 0;
00214 static LDAPSortKey **sss_keys = NULL;
00215 
00216 static int vlv = 0;
00217 static LDAPVLVInfo vlvInfo;
00218 static struct berval vlvValue;
00219 
00220 static int ldapsync = 0;
00221 static struct berval sync_cookie = { 0, NULL };
00222 static int sync_slimit = -1;
00223 
00224 /* cookie and morePagedResults moved to common.c */
00225 static int pagedResults = 0;
00226 static int pagePrompt = 1;
00227 static ber_int_t pageSize = 0;
00228 static ber_int_t entriesLeft = 0;
00229 static int npagedresponses;
00230 static int npagedentries;
00231 static int npagedreferences;
00232 static int npagedextended;
00233 static int npagedpartial;
00234 
00235 static LDAPControl *c = NULL;
00236 static int nctrls = 0;
00237 static int save_nctrls = 0;
00238 
00239 #ifdef LDAP_CONTROL_X_DEREF
00240 static int derefcrit;
00241 static LDAPDerefSpec *ds;
00242 static struct berval derefval;
00243 #endif
00244 
00245 static int
00246 ctrl_add( void )
00247 {
00248        LDAPControl   *tmpc;
00249 
00250        nctrls++;
00251        tmpc = realloc( c, sizeof( LDAPControl ) * nctrls );
00252        if ( tmpc == NULL ) {
00253               nctrls--;
00254               fprintf( stderr,
00255                      _("unable to make room for control; out of memory?\n"));
00256               return -1;
00257        }
00258        c = tmpc;
00259 
00260        return 0;
00261 }
00262 
00263 static void
00264 urlize(char *url)
00265 {
00266        char *p;
00267 
00268        if (*LDAP_DIRSEP != '/') {
00269               for (p = url; *p; p++) {
00270                      if (*p == *LDAP_DIRSEP)
00271                             *p = '/';
00272               }
00273        }
00274 }
00275 
00276 static int
00277 parse_vlv(char *cvalue)
00278 {
00279        char *keyp, *key2;
00280        int num1, num2;
00281 
00282        keyp = cvalue;
00283        if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
00284               fprintf( stderr,
00285                      _("VLV control value \"%s\" invalid\n"),
00286                      cvalue );
00287               return -1;
00288        }
00289        vlvInfo.ldvlv_before_count = num1;
00290        vlvInfo.ldvlv_after_count = num2;
00291        keyp = strchr( keyp, '/' ) + 1;
00292        key2 = strchr( keyp, '/' );
00293        if ( key2 ) {
00294               keyp = key2 + 1;
00295               if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
00296                      fprintf( stderr,
00297                             _("VLV control value \"%s\" invalid\n"),
00298                             cvalue );
00299                      return -1;
00300               }
00301               vlvInfo.ldvlv_offset = num1;
00302               vlvInfo.ldvlv_count = num2;
00303               vlvInfo.ldvlv_attrvalue = NULL;
00304        } else {
00305               key2 = strchr( keyp, ':' );
00306               if ( !key2 ) {
00307                      fprintf( stderr,
00308                             _("VLV control value \"%s\" invalid\n"),
00309                             cvalue );
00310                      return -1;
00311               }
00312               ber_str2bv( key2+1, 0, 0, &vlvValue );
00313               vlvInfo.ldvlv_attrvalue = &vlvValue;
00314        }
00315        return 0;
00316 }
00317 
00318 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
00319        "Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
00320 
00321 int
00322 handle_private_option( int i )
00323 {
00324        int crit, ival;
00325        char *cvalue, *next;
00326        switch ( i ) {
00327        case 'a':     /* set alias deref option */
00328               if ( strcasecmp( optarg, "never" ) == 0 ) {
00329                      deref = LDAP_DEREF_NEVER;
00330               } else if ( strncasecmp( optarg, "search", sizeof("search")-1 ) == 0 ) {
00331                      deref = LDAP_DEREF_SEARCHING;
00332               } else if ( strncasecmp( optarg, "find", sizeof("find")-1 ) == 0 ) {
00333                      deref = LDAP_DEREF_FINDING;
00334               } else if ( strcasecmp( optarg, "always" ) == 0 ) {
00335                      deref = LDAP_DEREF_ALWAYS;
00336               } else {
00337                      fprintf( stderr,
00338                             _("alias deref should be never, search, find, or always\n") );
00339                      usage();
00340               }
00341               break;
00342        case 'A':     /* retrieve attribute names only -- no values */
00343               ++attrsonly;
00344               break;
00345        case 'b': /* search base */
00346               base = ber_strdup( optarg );
00347               break;
00348        case 'E': /* search extensions */
00349               if( protocol == LDAP_VERSION2 ) {
00350                      fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
00351                             prog, protocol );
00352                      exit( EXIT_FAILURE );
00353               }
00354 
00355               /* should be extended to support comma separated list of
00356                *     [!]key[=value] parameters, e.g.  -E !foo,bar=567
00357                */
00358 
00359               crit = 0;
00360               cvalue = NULL;
00361               if( optarg[0] == '!' ) {
00362                      crit = 1;
00363                      optarg++;
00364               }
00365 
00366               control = ber_strdup( optarg );
00367               if ( (cvalue = strchr( control, '=' )) != NULL ) {
00368                      *cvalue++ = '\0';
00369               }
00370 
00371               if ( strcasecmp( control, "mv" ) == 0 ) {
00372                      /* ValuesReturnFilter control */
00373                      if( valuesReturnFilter ) {
00374                             fprintf( stderr,
00375                                    _("ValuesReturnFilter previously specified\n"));
00376                             exit( EXIT_FAILURE );
00377                      }
00378                      valuesReturnFilter= 1 + crit;
00379 
00380                      if ( cvalue == NULL ) {
00381                             fprintf( stderr,
00382                                    _("missing filter in ValuesReturnFilter control\n"));
00383                             exit( EXIT_FAILURE );
00384                      }
00385 
00386                      vrFilter = cvalue;
00387                      protocol = LDAP_VERSION3;
00388 
00389               } else if ( strcasecmp( control, "pr" ) == 0 ) {
00390                      int num, tmp;
00391                      /* PagedResults control */
00392                      if ( pagedResults != 0 ) {
00393                             fprintf( stderr,
00394                                    _("PagedResultsControl previously specified\n") );
00395                             exit( EXIT_FAILURE );
00396                      }
00397                      if ( vlv != 0 ) {
00398                             fprintf( stderr,
00399                                    _("PagedResultsControl incompatible with VLV\n") );
00400                             exit( EXIT_FAILURE );
00401                      }
00402 
00403                      if( cvalue != NULL ) {
00404                             char *promptp;
00405 
00406                             promptp = strchr( cvalue, '/' );
00407                             if ( promptp != NULL ) {
00408                                    *promptp++ = '\0';
00409                                    if ( strcasecmp( promptp, "prompt" ) == 0 ) {
00410                                           pagePrompt = 1;
00411                                    } else if ( strcasecmp( promptp, "noprompt" ) == 0) {
00412                                           pagePrompt = 0;
00413                                    } else {
00414                                           fprintf( stderr,
00415                                                  _("Invalid value for PagedResultsControl,"
00416                                                  " %s/%s.\n"), cvalue, promptp );
00417                                           exit( EXIT_FAILURE );
00418                                    }
00419                             }
00420                             num = sscanf( cvalue, "%d", &tmp );
00421                             if ( num != 1 ) {
00422                                    fprintf( stderr,
00423                                           _("Invalid value for PagedResultsControl, %s.\n"),
00424                                           cvalue );
00425                                    exit( EXIT_FAILURE );
00426                             }
00427                      } else {
00428                             fprintf(stderr, _("Invalid value for PagedResultsControl.\n"));
00429                             exit( EXIT_FAILURE );
00430                      }
00431                      pageSize = (ber_int_t) tmp;
00432                      pagedResults = 1 + crit;
00433 
00434 #ifdef LDAP_CONTROL_DONTUSECOPY
00435               } else if ( strcasecmp( control, "dontUseCopy" ) == 0 ) {
00436                      if( dontUseCopy ) {
00437                             fprintf( stderr,
00438                                    _("dontUseCopy control previously specified\n"));
00439                             exit( EXIT_FAILURE );
00440                      }
00441                      if( cvalue != NULL ) {
00442                             fprintf( stderr,
00443                               _("dontUseCopy: no control value expected\n") );
00444                             usage();
00445                      }
00446                      if( !crit ) {
00447                             fprintf( stderr,
00448                               _("dontUseCopy: critical flag required\n") );
00449                             usage();
00450                      }
00451 
00452                      dontUseCopy = 1 + crit;
00453 #endif
00454               } else if ( strcasecmp( control, "domainScope" ) == 0 ) {
00455                      if( domainScope ) {
00456                             fprintf( stderr,
00457                                    _("domainScope control previously specified\n"));
00458                             exit( EXIT_FAILURE );
00459                      }
00460                      if( cvalue != NULL ) {
00461                             fprintf( stderr,
00462                               _("domainScope: no control value expected\n") );
00463                             usage();
00464                      }
00465 
00466                      domainScope = 1 + crit;
00467 
00468               } else if ( strcasecmp( control, "sss" ) == 0 ) {
00469                      char *keyp;
00470                      if( sss ) {
00471                             fprintf( stderr,
00472                                    _("server side sorting control previously specified\n"));
00473                             exit( EXIT_FAILURE );
00474                      }
00475                      if( cvalue == NULL ) {
00476                             fprintf( stderr,
00477                               _("missing specification of sss control\n") );
00478                             exit( EXIT_FAILURE );
00479                      }
00480                      keyp = cvalue;
00481                      while ( ( keyp = strchr(keyp, '/') ) != NULL ) {
00482                             *keyp++ = ' ';
00483                      }
00484                      if ( ldap_create_sort_keylist( &sss_keys, cvalue )) {
00485                             fprintf( stderr,
00486                                    _("server side sorting control value \"%s\" invalid\n"),
00487                                    cvalue );
00488                             exit( EXIT_FAILURE );
00489                      }
00490 
00491                      sss = 1 + crit;
00492 
00493               } else if ( strcasecmp( control, "subentries" ) == 0 ) {
00494                      if( subentries ) {
00495                             fprintf( stderr,
00496                                    _("subentries control previously specified\n"));
00497                             exit( EXIT_FAILURE );
00498                      }
00499                      if( cvalue == NULL || strcasecmp( cvalue, "true") == 0 ) {
00500                             subentries = 2;
00501                      } else if ( strcasecmp( cvalue, "false") == 0 ) {
00502                             subentries = 1;
00503                      } else {
00504                             fprintf( stderr,
00505                                    _("subentries control value \"%s\" invalid\n"),
00506                                    cvalue );
00507                             exit( EXIT_FAILURE );
00508                      }
00509                      if( crit ) subentries *= -1;
00510 
00511               } else if ( strcasecmp( control, "sync" ) == 0 ) {
00512                      char *cookiep;
00513                      char *slimitp;
00514                      if ( ldapsync ) {
00515                             fprintf( stderr, _("sync control previously specified\n") );
00516                             exit( EXIT_FAILURE );
00517                      }
00518                      if ( cvalue == NULL ) {
00519                             fprintf( stderr, _("missing specification of sync control\n"));
00520                             exit( EXIT_FAILURE );
00521                      }
00522                      if ( strncasecmp( cvalue, "ro", 2 ) == 0 ) {
00523                             ldapsync = LDAP_SYNC_REFRESH_ONLY;
00524                             cookiep = strchr( cvalue, '/' );
00525                             if ( cookiep != NULL ) {
00526                                    cookiep++;
00527                                    if ( *cookiep != '\0' ) {
00528                                           ber_str2bv( cookiep, 0, 0, &sync_cookie );
00529                                    }
00530                             }
00531                      } else if ( strncasecmp( cvalue, "rp", 2 ) == 0 ) {
00532                             ldapsync = LDAP_SYNC_REFRESH_AND_PERSIST;
00533                             cookiep = strchr( cvalue, '/' );
00534                             if ( cookiep != NULL ) {
00535                                    *cookiep++ = '\0';   
00536                                    cvalue = cookiep;
00537                             }
00538                             slimitp = strchr( cvalue, '/' );
00539                             if ( slimitp != NULL ) {
00540                                    *slimitp++ = '\0';
00541                             }
00542                             if ( cookiep != NULL && *cookiep != '\0' )
00543                                    ber_str2bv( cookiep, 0, 0, &sync_cookie );
00544                             if ( slimitp != NULL && *slimitp != '\0' ) {
00545                                    ival = strtol( slimitp, &next, 10 );
00546                                    if ( next == NULL || next[0] != '\0' ) {
00547                                           fprintf( stderr, _("Unable to parse sync control value \"%s\"\n"), slimitp );
00548                                           exit( EXIT_FAILURE );
00549                                    }
00550                                    sync_slimit = ival;
00551                             }
00552                      } else {
00553                             fprintf( stderr, _("sync control value \"%s\" invalid\n"),
00554                                    cvalue );
00555                             exit( EXIT_FAILURE );
00556                      }
00557                      if ( crit ) ldapsync *= -1;
00558 
00559               } else if ( strcasecmp( control, "vlv" ) == 0 ) {
00560                      if( vlv ) {
00561                             fprintf( stderr,
00562                                    _("virtual list view control previously specified\n"));
00563                             exit( EXIT_FAILURE );
00564                      }
00565                      if ( pagedResults != 0 ) {
00566                             fprintf( stderr,
00567                                    _("PagedResultsControl incompatible with VLV\n") );
00568                             exit( EXIT_FAILURE );
00569                      }
00570                      if( cvalue == NULL ) {
00571                             fprintf( stderr,
00572                               _("missing specification of vlv control\n") );
00573                             exit( EXIT_FAILURE );
00574                      }
00575                      if ( parse_vlv( cvalue ))
00576                             exit( EXIT_FAILURE );
00577 
00578                      vlv = 1 + crit;
00579 
00580 #ifdef LDAP_CONTROL_X_DEREF
00581               } else if ( strcasecmp( control, "deref" ) == 0 ) {
00582                      int ispecs;
00583                      char **specs;
00584 
00585                      /* cvalue is something like
00586                       *
00587                       * derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]"
00588                       */
00589 
00590                      specs = ldap_str2charray( cvalue, ";" );
00591                      if ( specs == NULL ) {
00592                             fprintf( stderr, _("deref specs \"%s\" invalid\n"),
00593                                    cvalue );
00594                             exit( EXIT_FAILURE );
00595                      }
00596                      for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ )
00597                             /* count'em */ ;
00598 
00599                      ds = ldap_memcalloc( ispecs + 1, sizeof( LDAPDerefSpec ) );
00600                      if ( ds == NULL ) {
00601                             perror( "malloc" );
00602                             exit( EXIT_FAILURE );
00603                      }
00604 
00605                      for ( ispecs = 0; specs[ ispecs ] != NULL; ispecs++ ) {
00606                             char *ptr;
00607 
00608                             ptr = strchr( specs[ ispecs ], ':' );
00609                             if ( ptr == NULL ) {
00610                                    fprintf( stderr, _("deref specs \"%s\" invalid\n"),
00611                                           cvalue );
00612                                    exit( EXIT_FAILURE );
00613                             }
00614 
00615                             ds[ ispecs ].derefAttr = specs[ ispecs ];
00616                             *ptr++ = '\0';
00617                             ds[ ispecs ].attributes = ldap_str2charray( ptr, "," );
00618                      }
00619 
00620                      derefcrit = 1 + crit;
00621 
00622                      ldap_memfree( specs );
00623 #endif /* LDAP_CONTROL_X_DEREF */
00624 
00625               } else if ( tool_is_oid( control ) ) {
00626                      if ( ctrl_add() ) {
00627                             exit( EXIT_FAILURE );
00628                      }
00629 
00630                      /* OID */
00631                      c[ nctrls - 1 ].ldctl_oid = control;
00632 
00633                      /* value */
00634                      if ( cvalue == NULL ) {
00635                             c[ nctrls - 1 ].ldctl_value.bv_val = NULL;
00636                             c[ nctrls - 1 ].ldctl_value.bv_len = 0;
00637 
00638                      } else if ( cvalue[ 0 ] == ':' ) {
00639                             struct berval type;
00640                             struct berval value;
00641                             int freeval;
00642                             char save_c;
00643 
00644                             cvalue++;
00645 
00646                             /* dummy type "x"
00647                              * to use ldif_parse_line2() */
00648                             save_c = cvalue[ -2 ];
00649                             cvalue[ -2 ] = 'x';
00650                             ldif_parse_line2( &cvalue[ -2 ], &type,
00651                                    &value, &freeval );
00652                             cvalue[ -2 ] = save_c;
00653 
00654                             if ( freeval ) {
00655                                    c[ nctrls - 1 ].ldctl_value = value;
00656 
00657                             } else {
00658                                    ber_dupbv( &c[ nctrls - 1 ].ldctl_value, &value );
00659                             }
00660 
00661                      } else {
00662                             fprintf( stderr, "unable to parse %s control value\n", control );
00663                             exit( EXIT_FAILURE );
00664                             
00665                      }
00666 
00667                      /* criticality */
00668                      c[ nctrls - 1 ].ldctl_iscritical = crit;
00669 
00670               } else {
00671                      fprintf( stderr, _("Invalid search extension name: %s\n"),
00672                             control );
00673                      usage();
00674               }
00675               break;
00676        case 'F':     /* uri prefix */
00677               if( urlpre ) free( urlpre );
00678               urlpre = strdup( optarg );
00679               break;
00680        case 'l':     /* time limit */
00681               if ( strcasecmp( optarg, "none" ) == 0 ) {
00682                      timelimit = 0;
00683 
00684               } else if ( strcasecmp( optarg, "max" ) == 0 ) {
00685                      timelimit = LDAP_MAXINT;
00686 
00687               } else {
00688                      ival = strtol( optarg, &next, 10 );
00689                      if ( next == NULL || next[0] != '\0' ) {
00690                             fprintf( stderr,
00691                                    _("Unable to parse time limit \"%s\"\n"), optarg );
00692                             exit( EXIT_FAILURE );
00693                      }
00694                      timelimit = ival;
00695               }
00696               if( timelimit < 0 || timelimit > LDAP_MAXINT ) {
00697                      fprintf( stderr, _("%s: invalid timelimit (%d) specified\n"),
00698                             prog, timelimit );
00699                      exit( EXIT_FAILURE );
00700               }
00701               break;
00702        case 'L':     /* print entries in LDIF format */
00703               ++ldif;
00704               break;
00705        case 's':     /* search scope */
00706               if ( strncasecmp( optarg, "base", sizeof("base")-1 ) == 0 ) {
00707                      scope = LDAP_SCOPE_BASE;
00708               } else if ( strncasecmp( optarg, "one", sizeof("one")-1 ) == 0 ) {
00709                      scope = LDAP_SCOPE_ONELEVEL;
00710               } else if (( strcasecmp( optarg, "subordinate" ) == 0 )
00711                      || ( strcasecmp( optarg, "children" ) == 0 ))
00712               {
00713                      scope = LDAP_SCOPE_SUBORDINATE;
00714               } else if ( strncasecmp( optarg, "sub", sizeof("sub")-1 ) == 0 ) {
00715                      scope = LDAP_SCOPE_SUBTREE;
00716               } else {
00717                      fprintf( stderr, _("scope should be base, one, or sub\n") );
00718                      usage();
00719               }
00720               break;
00721        case 'S':     /* sort attribute */
00722               sortattr = strdup( optarg );
00723               break;
00724        case 't':     /* write attribute values to TMPDIR files */
00725               ++vals2tmp;
00726               break;
00727        case 'T':     /* tmpdir */
00728               if( tmpdir ) free( tmpdir );
00729               tmpdir = strdup( optarg );
00730               break;
00731        case 'u':     /* include UFN */
00732               ++includeufn;
00733               break;
00734        case 'z':     /* size limit */
00735               if ( strcasecmp( optarg, "none" ) == 0 ) {
00736                      sizelimit = 0;
00737 
00738               } else if ( strcasecmp( optarg, "max" ) == 0 ) {
00739                      sizelimit = LDAP_MAXINT;
00740 
00741               } else {
00742                      ival = strtol( optarg, &next, 10 );
00743                      if ( next == NULL || next[0] != '\0' ) {
00744                             fprintf( stderr,
00745                                    _("Unable to parse size limit \"%s\"\n"), optarg );
00746                             exit( EXIT_FAILURE );
00747                      }
00748                      sizelimit = ival;
00749               }
00750               if( sizelimit < 0 || sizelimit > LDAP_MAXINT ) {
00751                      fprintf( stderr, _("%s: invalid sizelimit (%d) specified\n"),
00752                             prog, sizelimit );
00753                      exit( EXIT_FAILURE );
00754               }
00755               break;
00756        default:
00757               return 0;
00758        }
00759        return 1;
00760 }
00761 
00762 
00763 static void
00764 private_conn_setup( LDAP *ld )
00765 {
00766        if (deref != -1 &&
00767               ldap_set_option( ld, LDAP_OPT_DEREF, (void *) &deref )
00768                      != LDAP_OPT_SUCCESS )
00769        {
00770               fprintf( stderr, _("Could not set LDAP_OPT_DEREF %d\n"), deref );
00771               tool_exit( ld, EXIT_FAILURE );
00772        }
00773 }
00774 
00775 int
00776 main( int argc, char **argv )
00777 {
00778        char          *filtpattern, **attrs = NULL, line[BUFSIZ];
00779        FILE          *fp = NULL;
00780        int                  rc, rc1, i, first;
00781        LDAP          *ld = NULL;
00782        BerElement    *seber = NULL, *vrber = NULL;
00783 
00784        BerElement      *syncber = NULL;
00785        struct berval   *syncbvalp = NULL;
00786        int           err;
00787 
00788        tool_init( TOOL_SEARCH );
00789 
00790        npagedresponses = npagedentries = npagedreferences =
00791               npagedextended = npagedpartial = 0;
00792 
00793        prog = lutil_progname( "ldapsearch", argc, argv );
00794 
00795        if((def_tmpdir = getenv("TMPDIR")) == NULL &&
00796           (def_tmpdir = getenv("TMP")) == NULL &&
00797           (def_tmpdir = getenv("TEMP")) == NULL )
00798        {
00799               def_tmpdir = LDAP_TMPDIR;
00800        }
00801 
00802        if ( !*def_tmpdir )
00803               def_tmpdir = LDAP_TMPDIR;
00804 
00805        def_urlpre = malloc( sizeof("file:////") + strlen(def_tmpdir) );
00806 
00807        if( def_urlpre == NULL ) {
00808               perror( "malloc" );
00809               return EXIT_FAILURE;
00810        }
00811 
00812        sprintf( def_urlpre, "file:///%s/",
00813               def_tmpdir[0] == *LDAP_DIRSEP ? &def_tmpdir[1] : def_tmpdir );
00814 
00815        urlize( def_urlpre );
00816 
00817        tool_args( argc, argv );
00818 
00819        if ( vlv && !sss ) {
00820               fprintf( stderr,
00821                      _("VLV control requires server side sort control\n" ));
00822               return EXIT_FAILURE;
00823        }
00824 
00825        if (( argc - optind < 1 ) ||
00826               ( *argv[optind] != '(' /*')'*/ &&
00827               ( strchr( argv[optind], '=' ) == NULL ) ) )
00828        {
00829               filtpattern = "(objectclass=*)";
00830        } else {
00831               filtpattern = argv[optind++];
00832        }
00833 
00834        if ( argv[optind] != NULL ) {
00835               attrs = &argv[optind];
00836        }
00837 
00838        if ( infile != NULL ) {
00839               int percent = 0;
00840        
00841               if ( infile[0] == '-' && infile[1] == '\0' ) {
00842                      fp = stdin;
00843               } else if (( fp = fopen( infile, "r" )) == NULL ) {
00844                      perror( infile );
00845                      return EXIT_FAILURE;
00846               }
00847 
00848               for( i=0 ; filtpattern[i] ; i++ ) {
00849                      if( filtpattern[i] == '%' ) {
00850                             if( percent ) {
00851                                    fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
00852                                           filtpattern );
00853                                    return EXIT_FAILURE;
00854                             }
00855 
00856                             percent++;
00857 
00858                             if( filtpattern[i+1] != 's' ) {
00859                                    fprintf( stderr, _("Bad filter pattern \"%s\"\n"),
00860                                           filtpattern );
00861                                    return EXIT_FAILURE;
00862                             }
00863                      }
00864               }
00865        }
00866 
00867        if ( tmpdir == NULL ) {
00868               tmpdir = def_tmpdir;
00869 
00870               if ( urlpre == NULL )
00871                      urlpre = def_urlpre;
00872        }
00873 
00874        if( urlpre == NULL ) {
00875               urlpre = malloc( sizeof("file:////") + strlen(tmpdir) );
00876 
00877               if( urlpre == NULL ) {
00878                      perror( "malloc" );
00879                      return EXIT_FAILURE;
00880               }
00881 
00882               sprintf( urlpre, "file:///%s/",
00883                      tmpdir[0] == *LDAP_DIRSEP ? &tmpdir[1] : tmpdir );
00884 
00885               urlize( urlpre );
00886        }
00887 
00888        if ( debug )
00889               ldif_debug = debug;
00890 
00891        ld = tool_conn_setup( 0, &private_conn_setup );
00892 
00893        tool_bind( ld );
00894 
00895 getNextPage:
00896        /* fp may have been closed, need to reopen if code jumps
00897         * back here to getNextPage.
00898         */
00899        if ( !fp && infile ) {
00900               if (( fp = fopen( infile, "r" )) == NULL ) {
00901                      perror( infile );
00902                      tool_exit( ld, EXIT_FAILURE );
00903               }
00904        }
00905        save_nctrls = nctrls;
00906        i = nctrls;
00907        if ( nctrls > 0
00908 #ifdef LDAP_CONTROL_DONTUSECOPY
00909               || dontUseCopy
00910 #endif
00911 #ifdef LDAP_CONTROL_X_DEREF
00912               || derefcrit
00913 #endif
00914               || domainScope
00915               || pagedResults
00916               || ldapsync
00917               || sss
00918               || subentries
00919               || valuesReturnFilter
00920               || vlv )
00921        {
00922 
00923 #ifdef LDAP_CONTROL_DONTUSECOPY
00924               if ( dontUseCopy ) {
00925                      if ( ctrl_add() ) {
00926                             tool_exit( ld, EXIT_FAILURE );
00927                      }
00928 
00929                      c[i].ldctl_oid = LDAP_CONTROL_DONTUSECOPY;
00930                      c[i].ldctl_value.bv_val = NULL;
00931                      c[i].ldctl_value.bv_len = 0;
00932                      c[i].ldctl_iscritical = dontUseCopy > 1;
00933                      i++;
00934               }
00935 #endif
00936 
00937               if ( domainScope ) {
00938                      if ( ctrl_add() ) {
00939                             tool_exit( ld, EXIT_FAILURE );
00940                      }
00941 
00942                      c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
00943                      c[i].ldctl_value.bv_val = NULL;
00944                      c[i].ldctl_value.bv_len = 0;
00945                      c[i].ldctl_iscritical = domainScope > 1;
00946                      i++;
00947               }
00948 
00949               if ( subentries ) {
00950                      if ( ctrl_add() ) {
00951                             tool_exit( ld, EXIT_FAILURE );
00952                      }
00953 
00954                      if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
00955                             tool_exit( ld, EXIT_FAILURE );
00956                      }
00957 
00958                      err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
00959                      if ( err == -1 ) {
00960                             ber_free( seber, 1 );
00961                             fprintf( stderr, _("Subentries control encoding error!\n") );
00962                             tool_exit( ld, EXIT_FAILURE );
00963                      }
00964 
00965                      if ( ber_flatten2( seber, &c[i].ldctl_value, 0 ) == -1 ) {
00966                             tool_exit( ld, EXIT_FAILURE );
00967                      }
00968 
00969                      c[i].ldctl_oid = LDAP_CONTROL_SUBENTRIES;
00970                      c[i].ldctl_iscritical = subentries < 1;
00971                      i++;
00972               }
00973 
00974               if ( ldapsync ) {
00975                      if ( ctrl_add() ) {
00976                             tool_exit( ld, EXIT_FAILURE );
00977                      }
00978 
00979                      if (( syncber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
00980                             tool_exit( ld, EXIT_FAILURE );
00981                      }
00982 
00983                      if ( sync_cookie.bv_len == 0 ) {
00984                             err = ber_printf( syncber, "{e}", abs(ldapsync) );
00985                      } else {
00986                             err = ber_printf( syncber, "{eO}", abs(ldapsync),
00987                                                  &sync_cookie );
00988                      }
00989 
00990                      if ( err == -1 ) {
00991                             ber_free( syncber, 1 );
00992                             fprintf( stderr, _("ldap sync control encoding error!\n") );
00993                             tool_exit( ld, EXIT_FAILURE );
00994                      }
00995 
00996                      if ( ber_flatten( syncber, &syncbvalp ) == -1 ) {
00997                             tool_exit( ld, EXIT_FAILURE );
00998                      }
00999 
01000                      c[i].ldctl_oid = LDAP_CONTROL_SYNC;
01001                      c[i].ldctl_value = (*syncbvalp);
01002                      c[i].ldctl_iscritical = ldapsync < 0;
01003                      i++;
01004               }
01005 
01006               if ( valuesReturnFilter ) {
01007                      if ( ctrl_add() ) {
01008                             tool_exit( ld, EXIT_FAILURE );
01009                      }
01010 
01011                      if (( vrber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
01012                             tool_exit( ld, EXIT_FAILURE );
01013                      }
01014 
01015                      if ( ( err = ldap_put_vrFilter( vrber, vrFilter ) ) == -1 ) {
01016                             ber_free( vrber, 1 );
01017                             fprintf( stderr, _("Bad ValuesReturnFilter: %s\n"), vrFilter );
01018                             tool_exit( ld, EXIT_FAILURE );
01019                      }
01020 
01021                      if ( ber_flatten2( vrber, &c[i].ldctl_value, 0 ) == -1 ) {
01022                             tool_exit( ld, EXIT_FAILURE );
01023                      }
01024 
01025                      c[i].ldctl_oid = LDAP_CONTROL_VALUESRETURNFILTER;
01026                      c[i].ldctl_iscritical = valuesReturnFilter > 1;
01027                      i++;
01028               }
01029 
01030               if ( pagedResults ) {
01031                      if ( ctrl_add() ) {
01032                             tool_exit( ld, EXIT_FAILURE );
01033                      }
01034 
01035                      if ( ldap_create_page_control_value( ld,
01036                             pageSize, &pr_cookie, &c[i].ldctl_value ) )
01037                      {
01038                             tool_exit( ld, EXIT_FAILURE );
01039                      }
01040 
01041                      if ( pr_cookie.bv_val != NULL ) {
01042                             ber_memfree( pr_cookie.bv_val );
01043                             pr_cookie.bv_val = NULL;
01044                             pr_cookie.bv_len = 0;
01045                      }
01046                      
01047                      c[i].ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
01048                      c[i].ldctl_iscritical = pagedResults > 1;
01049                      i++;
01050               }
01051 
01052               if ( sss ) {
01053                      if ( ctrl_add() ) {
01054                             tool_exit( ld, EXIT_FAILURE );
01055                      }
01056 
01057                      if ( ldap_create_sort_control_value( ld,
01058                             sss_keys, &c[i].ldctl_value ) )
01059                      {
01060                             tool_exit( ld, EXIT_FAILURE );
01061                      }
01062 
01063                      c[i].ldctl_oid = LDAP_CONTROL_SORTREQUEST;
01064                      c[i].ldctl_iscritical = sss > 1;
01065                      i++;
01066               }
01067 
01068               if ( vlv ) {
01069                      if ( ctrl_add() ) {
01070                             tool_exit( ld, EXIT_FAILURE );
01071                      }
01072 
01073                      if ( ldap_create_vlv_control_value( ld,
01074                             &vlvInfo, &c[i].ldctl_value ) )
01075                      {
01076                             tool_exit( ld, EXIT_FAILURE );
01077                      }
01078 
01079                      c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
01080                      c[i].ldctl_iscritical = sss > 1;
01081                      i++;
01082               }
01083 #ifdef LDAP_CONTROL_X_DEREF
01084               if ( derefcrit ) {
01085                      if ( derefval.bv_val == NULL ) {
01086                             int i;
01087 
01088                             assert( ds != NULL );
01089 
01090                             if ( ldap_create_deref_control_value( ld, ds, &derefval ) != LDAP_SUCCESS ) {
01091                                    tool_exit( ld, EXIT_FAILURE );
01092                             }
01093 
01094                             for ( i = 0; ds[ i ].derefAttr != NULL; i++ ) {
01095                                    ldap_memfree( ds[ i ].derefAttr );
01096                                    ldap_charray_free( ds[ i ].attributes );
01097                             }
01098                             ldap_memfree( ds );
01099                             ds = NULL;
01100                      }
01101 
01102                      if ( ctrl_add() ) {
01103                             tool_exit( ld, EXIT_FAILURE );
01104                      }
01105 
01106                      c[ i ].ldctl_iscritical = derefcrit > 1;
01107                      c[ i ].ldctl_oid = LDAP_CONTROL_X_DEREF;
01108                      c[ i ].ldctl_value = derefval;
01109                      i++;
01110               }
01111 #endif /* LDAP_CONTROL_X_DEREF */
01112        }
01113 
01114        tool_server_controls( ld, c, i );
01115 
01116        if ( seber ) ber_free( seber, 1 );
01117        if ( vrber ) ber_free( vrber, 1 );
01118 
01119        /* step back to the original number of controls, so that 
01120         * those set while parsing args are preserved */
01121        nctrls = save_nctrls;
01122 
01123        if ( verbose ) {
01124               fprintf( stderr, _("filter%s: %s\nrequesting: "),
01125                      infile != NULL ? _(" pattern") : "",
01126                      filtpattern );
01127 
01128               if ( attrs == NULL ) {
01129                      fprintf( stderr, _("All userApplication attributes") );
01130               } else {
01131                      for ( i = 0; attrs[ i ] != NULL; ++i ) {
01132                             fprintf( stderr, "%s ", attrs[ i ] );
01133                      }
01134               }
01135               fprintf( stderr, "\n" );
01136        }
01137 
01138        if ( ldif == 0 ) {
01139               printf( _("# extended LDIF\n") );
01140        } else if ( ldif < 3 ) {
01141               printf( _("version: %d\n\n"), 1 );
01142        }
01143 
01144        if (ldif < 2 ) {
01145               char   *realbase = base;
01146 
01147               if ( realbase == NULL ) {
01148                      ldap_get_option( ld, LDAP_OPT_DEFBASE, (void **)(char *)&realbase );
01149               }
01150               
01151               printf( "#\n" );
01152               printf(_("# LDAPv%d\n"), protocol);
01153               printf(_("# base <%s>%s with scope %s\n"),
01154                      realbase ? realbase : "",
01155                      ( realbase == NULL || realbase != base ) ? " (default)" : "",
01156                      ((scope == LDAP_SCOPE_BASE) ? "baseObject"
01157                             : ((scope == LDAP_SCOPE_ONELEVEL) ? "oneLevel"
01158                             : ((scope == LDAP_SCOPE_SUBORDINATE) ? "children"
01159                             : "subtree" ))));
01160               printf(_("# filter%s: %s\n"), infile != NULL ? _(" pattern") : "",
01161                      filtpattern);
01162               printf(_("# requesting: "));
01163 
01164               if ( attrs == NULL ) {
01165                      printf( _("ALL") );
01166               } else {
01167                      for ( i = 0; attrs[ i ] != NULL; ++i ) {
01168                             printf( "%s ", attrs[ i ] );
01169                      }
01170               }
01171 
01172               if ( manageDSAit ) {
01173                      printf(_("\n# with manageDSAit %scontrol"),
01174                             manageDSAit > 1 ? _("critical ") : "" );
01175               }
01176               if ( noop ) {
01177                      printf(_("\n# with noop %scontrol"),
01178                             noop > 1 ? _("critical ") : "" );
01179               }
01180               if ( subentries ) {
01181                      printf(_("\n# with subentries %scontrol: %s"),
01182                             subentries < 0 ? _("critical ") : "",
01183                             abs(subentries) == 1 ? "false" : "true" );
01184               }
01185               if ( valuesReturnFilter ) {
01186                      printf(_("\n# with valuesReturnFilter %scontrol: %s"),
01187                             valuesReturnFilter > 1 ? _("critical ") : "", vrFilter );
01188               }
01189               if ( pagedResults ) {
01190                      printf(_("\n# with pagedResults %scontrol: size=%d"),
01191                             (pagedResults > 1) ? _("critical ") : "", 
01192                             pageSize );
01193               }
01194               if ( sss ) {
01195                      printf(_("\n# with server side sorting %scontrol"),
01196                             sss > 1 ? _("critical ") : "" );
01197               }
01198               if ( vlv ) {
01199                      printf(_("\n# with virtual list view %scontrol: %d/%d"),
01200                             vlv > 1 ? _("critical ") : "",
01201                             vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count);
01202                      if ( vlvInfo.ldvlv_attrvalue )
01203                             printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val );
01204                      else
01205                             printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count );
01206               }
01207 #ifdef LDAP_CONTROL_X_DEREF
01208               if ( derefcrit ) {
01209                      printf(_("\n# with dereference %scontrol"),
01210                             derefcrit > 1 ? _("critical ") : "" );
01211               }
01212 #endif
01213 
01214               printf( _("\n#\n\n") );
01215 
01216               if ( realbase && realbase != base ) {
01217                      ldap_memfree( realbase );
01218               }
01219        }
01220 
01221        if ( infile == NULL ) {
01222               rc = dosearch( ld, base, scope, NULL, filtpattern,
01223                      attrs, attrsonly, NULL, NULL, NULL, sizelimit );
01224 
01225        } else {
01226               rc = 0;
01227               first = 1;
01228               while ( fgets( line, sizeof( line ), fp ) != NULL ) { 
01229                      line[ strlen( line ) - 1 ] = '\0';
01230                      if ( !first ) {
01231                             putchar( '\n' );
01232                      } else {
01233                             first = 0;
01234                      }
01235                      rc1 = dosearch( ld, base, scope, filtpattern, line,
01236                             attrs, attrsonly, NULL, NULL, NULL, sizelimit );
01237 
01238                      if ( rc1 != 0 ) {
01239                             rc = rc1;
01240                             if ( !contoper )
01241                                    break;
01242                      }
01243               }
01244               if ( fp != stdin ) {
01245                      fclose( fp );
01246                      fp = NULL;
01247               }
01248        }
01249 
01250        if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) {
01251               char   buf[12];
01252               int    i, moreEntries, tmpSize;
01253 
01254               /* Loop to get the next pages when 
01255                * enter is pressed on the terminal.
01256                */
01257               if ( pagePrompt != 0 ) {
01258                      if ( entriesLeft > 0 ) {
01259                             printf( _("Estimate entries: %d\n"), entriesLeft );
01260                      }
01261                      printf( _("Press [size] Enter for the next {%d|size} entries.\n"),
01262                             (int)pageSize );
01263                      i = 0;
01264                      moreEntries = getchar();
01265                      while ( moreEntries != EOF && moreEntries != '\n' ) { 
01266                             if ( i < (int)sizeof(buf) - 1 ) {
01267                                    buf[i] = moreEntries;
01268                                    i++;
01269                             }
01270                             moreEntries = getchar();
01271                      }
01272                      buf[i] = '\0';
01273 
01274                      if ( i > 0 && isdigit( (unsigned char)buf[0] ) ) {
01275                             int num = sscanf( buf, "%d", &tmpSize );
01276                             if ( num != 1 ) {
01277                                    fprintf( stderr,
01278                                           _("Invalid value for PagedResultsControl, %s.\n"), buf);
01279                                    tool_exit( ld, EXIT_FAILURE );
01280        
01281                             }
01282                             pageSize = (ber_int_t)tmpSize;
01283                      }
01284               }
01285 
01286               goto getNextPage;
01287        }
01288 
01289        if (( rc == LDAP_SUCCESS ) && vlv ) {
01290               char   buf[BUFSIZ];
01291               int    i, moreEntries;
01292 
01293               /* Loop to get the next window when 
01294                * enter is pressed on the terminal.
01295                */
01296               printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n"));
01297               i = 0;
01298               moreEntries = getchar();
01299               while ( moreEntries != EOF && moreEntries != '\n' ) { 
01300                      if ( i < (int)sizeof(buf) - 1 ) {
01301                             buf[i] = moreEntries;
01302                             i++;
01303                      }
01304                      moreEntries = getchar();
01305               }
01306               buf[i] = '\0';
01307               if ( buf[0] ) {
01308                      i = parse_vlv( strdup( buf ));
01309                      if ( i )
01310                             tool_exit( ld, EXIT_FAILURE );
01311               } else {
01312                      vlvInfo.ldvlv_attrvalue = NULL;
01313                      vlvInfo.ldvlv_count = vlvCount;
01314                      vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count;
01315               }
01316 
01317               if ( vlvInfo.ldvlv_context )
01318                      ber_bvfree( vlvInfo.ldvlv_context );
01319               vlvInfo.ldvlv_context = vlvContext;
01320 
01321               goto getNextPage;
01322        }
01323 
01324        if ( base != NULL ) {
01325               ber_memfree( base );
01326        }
01327        if ( control != NULL ) {
01328               ber_memfree( control );
01329        }
01330        if ( sss_keys != NULL ) {
01331               ldap_free_sort_keylist( sss_keys );
01332        }
01333        if ( derefval.bv_val != NULL ) {
01334               ldap_memfree( derefval.bv_val );
01335        }
01336        if ( urlpre != NULL ) {
01337               if ( def_urlpre != urlpre )
01338                      free( def_urlpre );
01339               free( urlpre );
01340        }
01341 
01342        if ( c ) {
01343               for ( ; save_nctrls-- > 0; ) {
01344                      ber_memfree( c[ save_nctrls ].ldctl_value.bv_val );
01345               }
01346               free( c );
01347               c = NULL;
01348        }
01349 
01350        tool_exit( ld, rc );
01351 }
01352 
01353 
01354 static int dosearch(
01355        LDAP   *ld,
01356        char   *base,
01357        int           scope,
01358        char   *filtpatt,
01359        char   *value,
01360        char   **attrs,
01361        int           attrsonly,
01362        LDAPControl **sctrls,
01363        LDAPControl **cctrls,
01364        struct timeval *timeout,
01365        int sizelimit )
01366 {
01367        char                 *filter;
01368        int                  rc, rc2 = LDAP_OTHER;
01369        int                  nresponses;
01370        int                  nentries;
01371        int                  nreferences;
01372        int                  nextended;
01373        int                  npartial;
01374        LDAPMessage          *res, *msg;
01375        ber_int_t            msgid;
01376        char                 *retoid = NULL;
01377        struct berval        *retdata = NULL;
01378        int                  nresponses_psearch = -1;
01379        int                  cancel_msgid = -1;
01380        struct timeval tv, *tvp = NULL;
01381        struct timeval tv_timelimit, *tv_timelimitp = NULL;
01382 
01383        if( filtpatt != NULL ) {
01384               size_t max_fsize = strlen( filtpatt ) + strlen( value ) + 1, outlen;
01385               filter = malloc( max_fsize );
01386               if( filter == NULL ) {
01387                      perror( "malloc" );
01388                      return EXIT_FAILURE;
01389               }
01390 
01391               outlen = snprintf( filter, max_fsize, filtpatt, value );
01392               if( outlen >= max_fsize ) {
01393                      fprintf( stderr, "Bad filter pattern: \"%s\"\n", filtpatt );
01394                      free( filter );
01395                      return EXIT_FAILURE;
01396               }
01397 
01398               if ( verbose ) {
01399                      fprintf( stderr, _("filter: %s\n"), filter );
01400               }
01401 
01402               if( ldif < 2 ) {
01403                      printf( _("#\n# filter: %s\n#\n"), filter );
01404               }
01405 
01406        } else {
01407               filter = value;
01408        }
01409 
01410        if ( dont ) {
01411               if ( filtpatt != NULL ) {
01412                      free( filter );
01413               }
01414               return LDAP_SUCCESS;
01415        }
01416 
01417        if ( timelimit > 0 ) {
01418               tv_timelimit.tv_sec = timelimit;
01419               tv_timelimit.tv_usec = 0;
01420               tv_timelimitp = &tv_timelimit;
01421        }
01422 
01423        rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
01424               sctrls, cctrls, tv_timelimitp, sizelimit, &msgid );
01425 
01426        if ( filtpatt != NULL ) {
01427               free( filter );
01428        }
01429 
01430        if( rc != LDAP_SUCCESS ) {
01431               tool_perror( "ldap_search_ext", rc, NULL, NULL, NULL, NULL );
01432               return( rc );
01433        }
01434 
01435        nresponses = nentries = nreferences = nextended = npartial = 0;
01436 
01437        res = NULL;
01438 
01439        if ( timelimit > 0 ) {
01440               /* disable timeout */
01441               tv.tv_sec = -1;
01442               tv.tv_usec = 0;
01443               tvp = &tv;
01444        }
01445 
01446        while ((rc = ldap_result( ld, LDAP_RES_ANY,
01447               sortattr ? LDAP_MSG_ALL : LDAP_MSG_ONE,
01448               tvp, &res )) > 0 )
01449        {
01450               if ( tool_check_abandon( ld, msgid ) ) {
01451                      return -1;
01452               }
01453 
01454               if( sortattr ) {
01455                      (void) ldap_sort_entries( ld, &res,
01456                             ( *sortattr == '\0' ) ? NULL : sortattr, strcasecmp );
01457               }
01458 
01459               for ( msg = ldap_first_message( ld, res );
01460                      msg != NULL;
01461                      msg = ldap_next_message( ld, msg ) )
01462               {
01463                      if ( nresponses++ ) putchar('\n');
01464                      if ( nresponses_psearch >= 0 ) 
01465                             nresponses_psearch++;
01466 
01467                      switch( ldap_msgtype( msg ) ) {
01468                      case LDAP_RES_SEARCH_ENTRY:
01469                             nentries++;
01470                             print_entry( ld, msg, attrsonly );
01471                             break;
01472 
01473                      case LDAP_RES_SEARCH_REFERENCE:
01474                             nreferences++;
01475                             print_reference( ld, msg );
01476                             break;
01477 
01478                      case LDAP_RES_EXTENDED:
01479                             nextended++;
01480                             print_extended( ld, msg );
01481 
01482                             if ( ldap_msgid( msg ) == 0 ) {
01483                                    /* unsolicited extended operation */
01484                                    goto done;
01485                             }
01486 
01487                             if ( cancel_msgid != -1 &&
01488                                           cancel_msgid == ldap_msgid( msg ) ) {
01489                                    printf(_("Cancelled \n"));
01490                                    printf(_("cancel_msgid = %d\n"), cancel_msgid);
01491                                    goto done;
01492                             }
01493                             break;
01494 
01495                      case LDAP_RES_SEARCH_RESULT:
01496                             /* pagedResults stuff is dealt with
01497                              * in tool_print_ctrls(), called by
01498                              * print_results(). */
01499                             rc2 = print_result( ld, msg, 1 );
01500                             if ( ldapsync == LDAP_SYNC_REFRESH_AND_PERSIST ) {
01501                                    break;
01502                             }
01503 
01504                             goto done;
01505 
01506                      case LDAP_RES_INTERMEDIATE:
01507                             npartial++;
01508                             ldap_parse_intermediate( ld, msg,
01509                                    &retoid, &retdata, NULL, 0 );
01510 
01511                             nresponses_psearch = 0;
01512 
01513                             if ( strcmp( retoid, LDAP_SYNC_INFO ) == 0 ) {
01514                                    printf(_("SyncInfo Received\n"));
01515                                    ldap_memfree( retoid );
01516                                    ber_bvfree( retdata );
01517                                    break;
01518                             }
01519 
01520                             print_partial( ld, msg );
01521                             ldap_memfree( retoid );
01522                             ber_bvfree( retdata );
01523                             goto done;
01524                      }
01525 
01526                      if ( ldapsync && sync_slimit != -1 &&
01527                                    nresponses_psearch >= sync_slimit ) {
01528                             BerElement *msgidber = NULL;
01529                             struct berval *msgidvalp = NULL;
01530                             msgidber = ber_alloc_t(LBER_USE_DER);
01531                             ber_printf(msgidber, "{i}", msgid);
01532                             ber_flatten(msgidber, &msgidvalp);
01533                             ldap_extended_operation(ld, LDAP_EXOP_CANCEL,
01534                                    msgidvalp, NULL, NULL, &cancel_msgid);
01535                             nresponses_psearch = -1;
01536                      }
01537               }
01538 
01539               ldap_msgfree( res );
01540        }
01541 
01542 done:
01543        if ( tvp == NULL && rc != LDAP_RES_SEARCH_RESULT ) {
01544               ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&rc2 );
01545        }
01546 
01547        ldap_msgfree( res );
01548 
01549        if ( pagedResults ) { 
01550               npagedresponses += nresponses;
01551               npagedentries += nentries;
01552               npagedextended += nextended;
01553               npagedpartial += npartial;
01554               npagedreferences += nreferences;
01555               if ( ( pr_morePagedResults == 0 ) && ( ldif < 2 ) ) {
01556                      printf( _("\n# numResponses: %d\n"), npagedresponses );
01557                      if( npagedentries ) {
01558                             printf( _("# numEntries: %d\n"), npagedentries );
01559                      }
01560                      if( npagedextended ) {
01561                             printf( _("# numExtended: %d\n"), npagedextended );
01562                      }
01563                      if( npagedpartial ) {
01564                             printf( _("# numPartial: %d\n"), npagedpartial );
01565                      }
01566                      if( npagedreferences ) {
01567                             printf( _("# numReferences: %d\n"), npagedreferences );
01568                      }
01569               }
01570        } else if ( ldif < 2 ) {
01571               printf( _("\n# numResponses: %d\n"), nresponses );
01572               if( nentries ) printf( _("# numEntries: %d\n"), nentries );
01573               if( nextended ) printf( _("# numExtended: %d\n"), nextended );
01574               if( npartial ) printf( _("# numPartial: %d\n"), npartial );
01575               if( nreferences ) printf( _("# numReferences: %d\n"), nreferences );
01576        }
01577 
01578        if ( rc != LDAP_RES_SEARCH_RESULT ) {
01579               tool_perror( "ldap_result", rc2, NULL, NULL, NULL, NULL );
01580        }
01581 
01582        return( rc2 );
01583 }
01584 
01585 /* This is the proposed new way of doing things.
01586  * It is more efficient, but the API is non-standard.
01587  */
01588 static void
01589 print_entry(
01590        LDAP   *ld,
01591        LDAPMessage   *entry,
01592        int           attrsonly)
01593 {
01594        char          *ufn = NULL;
01595        char   tmpfname[ 256 ];
01596        char   url[ 256 ];
01597        int                  i, rc;
01598        BerElement           *ber = NULL;
01599        struct berval        bv, *bvals, **bvp = &bvals;
01600        LDAPControl **ctrls = NULL;
01601        FILE          *tmpfp;
01602 
01603        rc = ldap_get_dn_ber( ld, entry, &ber, &bv );
01604 
01605        if ( ldif < 2 ) {
01606               ufn = ldap_dn2ufn( bv.bv_val );
01607               tool_write_ldif( LDIF_PUT_COMMENT, NULL, ufn, ufn ? strlen( ufn ) : 0 );
01608        }
01609        tool_write_ldif( LDIF_PUT_VALUE, "dn", bv.bv_val, bv.bv_len );
01610 
01611        rc = ldap_get_entry_controls( ld, entry, &ctrls );
01612        if( rc != LDAP_SUCCESS ) {
01613               fprintf(stderr, _("print_entry: %d\n"), rc );
01614               tool_perror( "ldap_get_entry_controls", rc, NULL, NULL, NULL, NULL );
01615               tool_exit( ld, EXIT_FAILURE );
01616        }
01617 
01618        if( ctrls ) {
01619               tool_print_ctrls( ld, ctrls );
01620               ldap_controls_free( ctrls );
01621        }
01622 
01623        if ( includeufn ) {
01624               if( ufn == NULL ) {
01625                      ufn = ldap_dn2ufn( bv.bv_val );
01626               }
01627               tool_write_ldif( LDIF_PUT_VALUE, "ufn", ufn, ufn ? strlen( ufn ) : 0 );
01628        }
01629 
01630        if( ufn != NULL ) ldap_memfree( ufn );
01631 
01632        if ( attrsonly ) bvp = NULL;
01633 
01634        for ( rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp );
01635               rc == LDAP_SUCCESS;
01636               rc = ldap_get_attribute_ber( ld, entry, ber, &bv, bvp ) )
01637        {
01638               if (bv.bv_val == NULL) break;
01639 
01640               if ( attrsonly ) {
01641                      tool_write_ldif( LDIF_PUT_NOVALUE, bv.bv_val, NULL, 0 );
01642 
01643               } else if ( bvals ) {
01644                      for ( i = 0; bvals[i].bv_val != NULL; i++ ) {
01645                             if ( vals2tmp > 1 || ( vals2tmp &&
01646                                    ldif_is_not_printable( bvals[i].bv_val, bvals[i].bv_len )))
01647                             {
01648                                    int tmpfd;
01649                                    /* write value to file */
01650                                    snprintf( tmpfname, sizeof tmpfname,
01651                                           "%s" LDAP_DIRSEP "ldapsearch-%s-XXXXXX",
01652                                           tmpdir, bv.bv_val );
01653                                    tmpfp = NULL;
01654 
01655                                    tmpfd = mkstemp( tmpfname );
01656 
01657                                    if ( tmpfd < 0  ) {
01658                                           perror( tmpfname );
01659                                           continue;
01660                                    }
01661 
01662                                    if (( tmpfp = fdopen( tmpfd, "w")) == NULL ) {
01663                                           perror( tmpfname );
01664                                           continue;
01665                                    }
01666 
01667                                    if ( fwrite( bvals[ i ].bv_val,
01668                                           bvals[ i ].bv_len, 1, tmpfp ) == 0 )
01669                                    {
01670                                           perror( tmpfname );
01671                                           fclose( tmpfp );
01672                                           continue;
01673                                    }
01674 
01675                                    fclose( tmpfp );
01676 
01677                                    snprintf( url, sizeof url, "%s%s", urlpre,
01678                                           &tmpfname[strlen(tmpdir) + sizeof(LDAP_DIRSEP) - 1] );
01679 
01680                                    urlize( url );
01681                                    tool_write_ldif( LDIF_PUT_URL, bv.bv_val, url, strlen( url ));
01682 
01683                             } else {
01684                                    tool_write_ldif( LDIF_PUT_VALUE, bv.bv_val,
01685                                           bvals[ i ].bv_val, bvals[ i ].bv_len );
01686                             }
01687                      }
01688                      ber_memfree( bvals );
01689               }
01690        }
01691 
01692        if( ber != NULL ) {
01693               ber_free( ber, 0 );
01694        }
01695 }
01696 
01697 static void print_reference(
01698        LDAP *ld,
01699        LDAPMessage *reference )
01700 {
01701        int rc;
01702        char **refs = NULL;
01703        LDAPControl **ctrls;
01704 
01705        if( ldif < 2 ) {
01706               printf(_("# search reference\n"));
01707        }
01708 
01709        rc = ldap_parse_reference( ld, reference, &refs, &ctrls, 0 );
01710 
01711        if( rc != LDAP_SUCCESS ) {
01712               tool_perror( "ldap_parse_reference", rc, NULL, NULL, NULL, NULL );
01713               tool_exit( ld, EXIT_FAILURE );
01714        }
01715 
01716        if( refs ) {
01717               int i;
01718               for( i=0; refs[i] != NULL; i++ ) {
01719                      tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
01720                             "ref", refs[i], strlen(refs[i]) );
01721               }
01722               ber_memvfree( (void **) refs );
01723        }
01724 
01725        if( ctrls ) {
01726               tool_print_ctrls( ld, ctrls );
01727               ldap_controls_free( ctrls );
01728        }
01729 }
01730 
01731 static void print_extended(
01732        LDAP *ld,
01733        LDAPMessage *extended )
01734 {
01735        int rc;
01736        char *retoid = NULL;
01737        struct berval *retdata = NULL;
01738 
01739        if( ldif < 2 ) {
01740               printf(_("# extended result response\n"));
01741        }
01742 
01743        rc = ldap_parse_extended_result( ld, extended,
01744               &retoid, &retdata, 0 );
01745 
01746        if( rc != LDAP_SUCCESS ) {
01747               tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL );
01748               tool_exit( ld, EXIT_FAILURE );
01749        }
01750 
01751        if ( ldif < 2 ) {
01752               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
01753                      "extended", retoid, retoid ? strlen(retoid) : 0 );
01754        }
01755        ber_memfree( retoid );
01756 
01757        if(retdata) {
01758               if ( ldif < 2 ) {
01759                      tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
01760                             "data", retdata->bv_val, retdata->bv_len );
01761               }
01762               ber_bvfree( retdata );
01763        }
01764 
01765        print_result( ld, extended, 0 );
01766 }
01767 
01768 static void print_partial(
01769        LDAP *ld,
01770        LDAPMessage *partial )
01771 {
01772        int rc;
01773        char *retoid = NULL;
01774        struct berval *retdata = NULL;
01775        LDAPControl **ctrls = NULL;
01776 
01777        if( ldif < 2 ) {
01778               printf(_("# extended partial response\n"));
01779        }
01780 
01781        rc = ldap_parse_intermediate( ld, partial,
01782               &retoid, &retdata, &ctrls, 0 );
01783 
01784        if( rc != LDAP_SUCCESS ) {
01785               tool_perror( "ldap_parse_intermediate", rc, NULL, NULL, NULL, NULL );
01786               tool_exit( ld, EXIT_FAILURE );
01787        }
01788 
01789        if ( ldif < 2 ) {
01790               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
01791                      "partial", retoid, retoid ? strlen(retoid) : 0 );
01792        }
01793 
01794        ber_memfree( retoid );
01795 
01796        if( retdata ) {
01797               if ( ldif < 2 ) {
01798                      tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY,
01799                             "data", retdata->bv_val, retdata->bv_len );
01800               }
01801 
01802               ber_bvfree( retdata );
01803        }
01804 
01805        if( ctrls ) {
01806               tool_print_ctrls( ld, ctrls );
01807               ldap_controls_free( ctrls );
01808        }
01809 }
01810 
01811 static int print_result(
01812        LDAP *ld,
01813        LDAPMessage *result, int search )
01814 {
01815        int rc;
01816        int err;
01817        char *matcheddn = NULL;
01818        char *text = NULL;
01819        char **refs = NULL;
01820        LDAPControl **ctrls = NULL;
01821 
01822        if( search ) {
01823               if ( ldif < 2 ) {
01824                      printf(_("# search result\n"));
01825               }
01826               if ( ldif < 1 ) {
01827                      printf("%s: %d\n", _("search"), ldap_msgid(result) );
01828               }
01829        }
01830 
01831        rc = ldap_parse_result( ld, result,
01832               &err, &matcheddn, &text, &refs, &ctrls, 0 );
01833 
01834        if( rc != LDAP_SUCCESS ) {
01835               tool_perror( "ldap_parse_result", rc, NULL, NULL, NULL, NULL );
01836               tool_exit( ld, EXIT_FAILURE );
01837        }
01838 
01839 
01840        if( !ldif ) {
01841               printf( _("result: %d %s\n"), err, ldap_err2string(err) );
01842 
01843        } else if ( err != LDAP_SUCCESS ) {
01844               fprintf( stderr, "%s (%d)\n", ldap_err2string(err), err );
01845        }
01846 
01847        if( matcheddn ) {
01848               if( *matcheddn ) {
01849               if( !ldif ) {
01850                      tool_write_ldif( LDIF_PUT_VALUE,
01851                             "matchedDN", matcheddn, strlen(matcheddn) );
01852               } else {
01853                      fprintf( stderr, _("Matched DN: %s\n"), matcheddn );
01854               }
01855               }
01856 
01857               ber_memfree( matcheddn );
01858        }
01859 
01860        if( text ) {
01861               if( *text ) {
01862                      if( !ldif ) {
01863                             if ( err == LDAP_PARTIAL_RESULTS ) {
01864                                    char   *line;
01865 
01866                                    for ( line = text; line != NULL; ) {
01867                                           char   *next = strchr( line, '\n' );
01868 
01869                                           tool_write_ldif( LDIF_PUT_TEXT,
01870                                                  "text", line,
01871                                                  next ? (size_t) (next - line) : strlen( line ));
01872 
01873                                           line = next ? next + 1 : NULL;
01874                                    }
01875 
01876                             } else {
01877                                    tool_write_ldif( LDIF_PUT_TEXT, "text",
01878                                           text, strlen(text) );
01879                             }
01880                      } else {
01881                             fprintf( stderr, _("Additional information: %s\n"), text );
01882                      }
01883               }
01884 
01885               ber_memfree( text );
01886        }
01887 
01888        if( refs ) {
01889               int i;
01890               for( i=0; refs[i] != NULL; i++ ) {
01891                      if( !ldif ) {
01892                             tool_write_ldif( LDIF_PUT_VALUE, "ref", refs[i], strlen(refs[i]) );
01893                      } else {
01894                             fprintf( stderr, _("Referral: %s\n"), refs[i] );
01895                      }
01896               }
01897 
01898               ber_memvfree( (void **) refs );
01899        }
01900 
01901        pr_morePagedResults = 0;
01902 
01903        if( ctrls ) {
01904               tool_print_ctrls( ld, ctrls );
01905               ldap_controls_free( ctrls );
01906        }
01907 
01908        return err;
01909 }