Back to index

lightning-sunbird  0.9+nobinonly
test.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /* test.c - a simple test harness. */
00039 #include <stdio.h>
00040 #include <ctype.h>
00041 #include <string.h>
00042 #include <stdlib.h>
00043 #ifdef MACOS
00044 #ifdef THINK_C
00045 #include <console.h>
00046 #include <unix.h>
00047 #include <fcntl.h>
00048 #endif /* THINK_C */
00049 #include "macos.h"
00050 #else /* MACOS */
00051 #if defined( DOS )
00052 #include "msdos.h"
00053 #if defined( WINSOCK ) 
00054 #include "console.h"
00055 #endif /* WINSOCK */
00056 #else /* DOS */
00057 #ifdef _WINDOWS
00058 #include <windows.h>
00059 #include <stdio.h>
00060 #include <fcntl.h>
00061 #include <stdlib.h>
00062 //#include "console.h"
00063 #else /* _WINDOWS */
00064 #include <sys/types.h>
00065 #include <sys/socket.h>
00066 #include <sys/time.h>
00067 #include <sys/stat.h>
00068 #include <sys/file.h>
00069 #ifndef VMS
00070 #include <fcntl.h>
00071 #include <unistd.h>
00072 #endif /* VMS */
00073 #endif /* _WINDOWS */
00074 #endif /* DOS */
00075 #endif /* MACOS */
00076 
00077 #undef NET_SSL
00078 
00079 #if defined(NET_SSL)
00080 #include <sec.h>
00081 static SECCertDBHandle        certdbhandle;
00082 #endif
00083 
00084 #include "ldap.h"
00085 #include "disptmpl.h"
00086 #include "ldaplog.h"
00087 #ifndef NO_LIBLCACHE
00088 #include "lcache.h"
00089 #endif /* !NO_LIBLCACHE */
00090 
00091 #if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS )
00092 #define MOD_USE_BVALS
00093 #endif /* !PCNFS && !WINSOCK && !MACOS */
00094 
00095 static void handle_result( LDAP *ld, LDAPMessage *lm, int onlyone );
00096 static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s );
00097 static void print_controls( LDAPControl **ctrls, int freeit );
00098 static void print_referrals( char **refs, int freeit );
00099 static void print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone );
00100 static char *changetype_num2string( int chgtype );
00101 static void print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone );
00102 static void free_list( char **list );
00103 static int entry2textwrite( void *fp, char *buf, int len );
00104 static void bprint( char *data, int len );
00105 static char **string2words( char *str, char *delims );
00106 static const char * url_parse_err2string( int e );
00107 
00108 char *dnsuffix;
00109 
00110 #ifndef WINSOCK
00111 static char *
00112 getline( char *line, int len, FILE *fp, char *prompt )
00113 {
00114        printf(prompt);
00115 
00116        if ( fgets( line, len, fp ) == NULL )
00117               return( NULL );
00118 
00119        line[ strlen( line ) - 1 ] = '\0';
00120 
00121        return( line );
00122 }
00123 #endif /* WINSOCK */
00124 
00125 static char **
00126 get_list( char *prompt )
00127 {
00128        static char   buf[256];
00129        int           num;
00130        char          **result;
00131 
00132        num = 0;
00133        result = (char **) 0;
00134        while ( 1 ) {
00135               getline( buf, sizeof(buf), stdin, prompt );
00136 
00137               if ( *buf == '\0' )
00138                      break;
00139 
00140               if ( result == (char **) 0 )
00141                      result = (char **) malloc( sizeof(char *) );
00142               else
00143                      result = (char **) realloc( result,
00144                          sizeof(char *) * (num + 1) );
00145 
00146               result[num++] = (char *) strdup( buf );
00147        }
00148        if ( result == (char **) 0 )
00149               return( NULL );
00150        result = (char **) realloc( result, sizeof(char *) * (num + 1) );
00151        result[num] = NULL;
00152 
00153        return( result );
00154 }
00155 
00156 
00157 static void
00158 free_list( char **list )
00159 {
00160        int    i;
00161 
00162        if ( list != NULL ) {
00163               for ( i = 0; list[ i ] != NULL; ++i ) {
00164                      free( list[ i ] );
00165               }
00166               free( (char *)list );
00167        }
00168 }
00169 
00170 
00171 #ifdef MOD_USE_BVALS
00172 static int
00173 file_read( char *path, struct berval *bv )
00174 {
00175        FILE          *fp;
00176        long          rlen;
00177        int           eof;
00178 
00179        if (( fp = fopen( path, "r" )) == NULL ) {
00180               perror( path );
00181               return( -1 );
00182        }
00183 
00184        if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
00185               perror( path );
00186               fclose( fp );
00187               return( -1 );
00188        }
00189 
00190        bv->bv_len = ftell( fp );
00191 
00192        if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
00193               perror( "malloc" );
00194               fclose( fp );
00195               return( -1 );
00196        }
00197 
00198        if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
00199               perror( path );
00200               fclose( fp );
00201               return( -1 );
00202        }
00203 
00204        rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
00205        eof = feof( fp );
00206        fclose( fp );
00207 
00208        if ( (unsigned long)rlen != bv->bv_len ) {
00209               perror( path );
00210               free( bv->bv_val );
00211               return( -1 );
00212        }
00213 
00214        return( bv->bv_len );
00215 }
00216 #endif /* MOD_USE_BVALS */
00217 
00218 
00219 static LDAPMod **
00220 get_modlist( char *prompt1, char *prompt2, char *prompt3 )
00221 {
00222        static char   buf[256];
00223        int           num;
00224        LDAPMod              tmp;
00225        LDAPMod              **result;
00226 #ifdef MOD_USE_BVALS
00227        struct berval **bvals;
00228 #endif /* MOD_USE_BVALS */
00229 
00230        num = 0;
00231        result = NULL;
00232        while ( 1 ) {
00233               if ( prompt1 ) {
00234                      getline( buf, sizeof(buf), stdin, prompt1 );
00235                      tmp.mod_op = atoi( buf );
00236 
00237                      if ( tmp.mod_op == -1 || buf[0] == '\0' )
00238                             break;
00239               } else {
00240                      tmp.mod_op = 0;
00241               }
00242 
00243               getline( buf, sizeof(buf), stdin, prompt2 );
00244               if ( buf[0] == '\0' )
00245                      break;
00246               tmp.mod_type = strdup( buf );
00247 
00248               tmp.mod_values = get_list( prompt3 );
00249 #ifdef MOD_USE_BVALS
00250               if ( tmp.mod_values != NULL ) {
00251                      int    i;
00252 
00253                      for ( i = 0; tmp.mod_values[i] != NULL; ++i )
00254                             ;
00255                      bvals = (struct berval **)calloc( i + 1,
00256                          sizeof( struct berval *));
00257                      for ( i = 0; tmp.mod_values[i] != NULL; ++i ) {
00258                             bvals[i] = (struct berval *)malloc(
00259                                 sizeof( struct berval ));
00260                             if ( strncmp( tmp.mod_values[i], "{FILE}",
00261                                 6 ) == 0 ) {
00262                                    if ( file_read( tmp.mod_values[i] + 6,
00263                                        bvals[i] ) < 0 ) {
00264                                           return( NULL );
00265                                    }
00266                             } else {
00267                                    bvals[i]->bv_val = tmp.mod_values[i];
00268                                    bvals[i]->bv_len =
00269                                        strlen( tmp.mod_values[i] );
00270                             }
00271                      }
00272                      tmp.mod_bvalues = bvals;
00273                      tmp.mod_op |= LDAP_MOD_BVALUES;
00274               }
00275 #endif /* MOD_USE_BVALS */
00276 
00277               if ( result == NULL )
00278                      result = (LDAPMod **) malloc( sizeof(LDAPMod *) );
00279               else
00280                      result = (LDAPMod **) realloc( result,
00281                          sizeof(LDAPMod *) * (num + 1) );
00282 
00283               result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) );
00284               *(result[num]) = tmp;       /* struct copy */
00285               num++;
00286        }
00287        if ( result == NULL )
00288               return( NULL );
00289        result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) );
00290        result[num] = NULL;
00291 
00292        return( result );
00293 }
00294 
00295 
00296 int LDAP_CALL LDAP_CALLBACK
00297 bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp,
00298        int freeit, void *dummy )
00299 {
00300        static char   dn[256], passwd[256];
00301 
00302        if ( !freeit ) {
00303 #ifdef KERBEROS
00304               getline( dn, sizeof(dn), stdin,
00305                   "re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " );
00306               if (( *authmethodp = atoi( dn )) == 3 ) {
00307                      *authmethodp = LDAP_AUTH_KRBV4;
00308               } else {
00309                      *authmethodp |= 0x80;
00310               }
00311 #else /* KERBEROS */
00312               *authmethodp = LDAP_AUTH_SIMPLE;
00313 #endif /* KERBEROS */
00314 
00315               getline( dn, sizeof(dn), stdin, "re-bind dn? " );
00316               strcat( dn, dnsuffix );
00317               *dnp = dn;
00318 
00319               if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
00320                      getline( passwd, sizeof(passwd), stdin,
00321                          "re-bind password? " );
00322               } else {
00323                      passwd[0] = '\0';
00324               }
00325               *passwdp = passwd;
00326        }
00327 
00328        return( LDAP_SUCCESS );
00329 }
00330 
00331 
00332 #define HEX2BIN( h ) ( (h) >= '0' && (h) <='0' ? (h) - '0' : (h) - 'A' + 10 )
00333 
00334 void
00335 berval_from_hex( struct berval *bvp, char *hexstr )
00336 {
00337     char      *src, *dst, c, abyte;
00338 
00339     dst = bvp->bv_val;
00340     bvp->bv_len = 0;
00341     src = hexstr;
00342     while ( *src != '\0' ) {
00343        c = *src;
00344        if ( isupper( c )) {
00345               c = tolower( c );
00346        }
00347        abyte = HEX2BIN( c ) << 4;
00348 
00349        ++src;
00350        c = *src;
00351        if ( isupper( c )) {
00352               c = tolower( c );
00353        }
00354        abyte |= HEX2BIN( c );
00355        ++src;
00356 
00357        *dst++ = abyte;
00358        ++bvp->bv_len;
00359     }
00360 }
00361 
00362 
00363 static void
00364 add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
00365 {
00366        int    i;
00367 
00368        if ( *ctrlsp == NULL ) {
00369               *ctrlsp = (LDAPControl **) calloc( 2, sizeof(LDAPControl *) );
00370               i = 0;
00371        } else {
00372               for ( i = 0; (*ctrlsp)[i] != NULL; i++ ) {
00373                      ;      /* NULL */
00374               }
00375               *ctrlsp = (LDAPControl **) realloc( *ctrlsp,
00376                   (i + 2) * sizeof(LDAPControl *) );
00377        }
00378        (*ctrlsp)[i] = newctrl;
00379        (*ctrlsp)[i+1] = NULL;
00380 }
00381 
00382 
00383 #ifdef TEST_CUSTOM_MALLOC
00384 
00385 typedef struct my_malloc_info {
00386        long   mmi_magic;
00387        size_t mmi_actualsize;
00388 } MyMallocInfo;
00389 #define MY_MALLOC_MAGIC_NUMBER            0x19940618
00390 
00391 #define MY_MALLOC_CHECK_MAGIC( p ) if ( ((MyMallocInfo *)( (p) - sizeof()
00392 
00393 void *
00394 my_malloc( size_t size )
00395 {
00396        void          *p;
00397        MyMallocInfo  *mmip;
00398 
00399        if (( p = malloc( size + sizeof( struct my_malloc_info ))) != NULL ) {
00400               mmip = (MyMallocInfo *)p;
00401               mmip->mmi_magic = MY_MALLOC_MAGIC_NUMBER;
00402               mmip->mmi_actualsize = size;
00403        }
00404 
00405        fprintf( stderr, "my_malloc: allocated ptr 0x%x, size %ld\n",
00406            p,  mmip->mmi_actualsize );
00407 
00408        return( (char *)p + sizeof( MyMallocInfo ));
00409 }
00410 
00411 
00412 void *
00413 my_calloc( size_t nelem, size_t elsize )
00414 {
00415        void   *p;
00416 
00417        if (( p = my_malloc( nelem * elsize )) != NULL ) {
00418               memset( p, 0, nelem * elsize );
00419        }
00420 
00421        return( p );
00422 }
00423 
00424 
00425 void
00426 my_free( void *ptr )
00427 {
00428        char          *p;
00429        MyMallocInfo  *mmip;
00430 
00431        p = (char *)ptr;
00432        p -= sizeof( MyMallocInfo );
00433        mmip = (MyMallocInfo *)p;
00434        if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) {
00435               fprintf( stderr,
00436                   "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr );
00437               exit( 1 );
00438        }
00439 
00440        fprintf( stderr, "my_free: freeing ptr 0x%x, size %ld\n",
00441            p,  mmip->mmi_actualsize );
00442 
00443        memset( p, 0, mmip->mmi_actualsize + sizeof( MyMallocInfo ));
00444        free( p );
00445 }
00446 
00447 
00448 void *
00449 my_realloc( void *ptr, size_t size )
00450 {
00451        void          *p;
00452        MyMallocInfo  *mmip;
00453 
00454        if ( ptr == NULL ) {
00455               return( my_malloc( size ));
00456        }
00457 
00458        mmip = (MyMallocInfo *)( (char *)ptr - sizeof( MyMallocInfo ));
00459        if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) {
00460               fprintf( stderr,
00461                   "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr );
00462               exit( 1 );
00463        }
00464 
00465        if ( size <= mmip->mmi_actualsize ) {     /* current block big enough? */
00466               return( ptr );
00467        }
00468 
00469        if (( p = my_malloc( size )) != NULL ) {
00470               memcpy( p, ptr, mmip->mmi_actualsize );
00471               my_free( ptr );
00472        }
00473 
00474        return( p );
00475 }
00476 #endif /* TEST_CUSTOM_MALLOC */
00477 
00478 int
00479 #ifdef WINSOCK
00480 ldapmain(
00481 #else /* WINSOCK */
00482 main(
00483 #endif /* WINSOCK */
00484        int argc, char **argv )
00485 {
00486        LDAP          *ld;
00487        int           rc, i, c, port, cldapflg, errflg, method, id, msgtype;
00488        int           version;
00489        char          line[256], command1, command2, command3;
00490        char          passwd[64], dn[256], rdn[64], attr[64], value[256];
00491        char          filter[256], *host, **types;
00492        char          **exdn, *fnname;
00493        int           bound, all, scope, attrsonly, optval, ldapversion;
00494        LDAPMessage   *res;
00495        LDAPMod              **mods, **attrs;
00496        struct timeval       timeout, *tvp;
00497        char          *copyfname = NULL;
00498        int           copyoptions = 0;
00499        LDAPURLDesc   *ludp;
00500        struct ldap_disptmpl *tmpllist = NULL;
00501        int           changetypes, changesonly, return_echg_ctls;
00502        LDAPControl   **tmpctrls, *newctrl, **controls = NULL;
00503        char          *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file] [-V protocolversion]\n";
00504 
00505        extern char   *optarg;
00506        extern int    optind;
00507 
00508 #ifdef MACOS
00509        if (( argv = get_list( "cmd line arg?" )) == NULL ) {
00510               exit( 1 );
00511        }
00512        for ( argc = 0; argv[ argc ] != NULL; ++argc ) {
00513               ;
00514        }
00515 #endif /* MACOS */
00516 
00517 #ifdef TEST_CUSTOM_MALLOC
00518         {
00519               struct ldap_memalloc_fns    memalloc_fns;
00520 
00521               memalloc_fns.ldapmem_malloc = my_malloc;
00522               memalloc_fns.ldapmem_calloc = my_calloc;
00523               memalloc_fns.ldapmem_realloc = my_realloc;
00524               memalloc_fns.ldapmem_free = my_free;
00525 
00526               if ( ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS,
00527                   &memalloc_fns ) != 0 ) {
00528                      fputs( "ldap_set_option failed\n", stderr );
00529                      exit( 1 );
00530               }
00531        }
00532 #endif /* TEST_CUSTOM_MALLOC */
00533 
00534        host = NULL;
00535        port = LDAP_PORT;
00536        dnsuffix = "";
00537        cldapflg = errflg = 0;
00538        ldapversion = 0;     /* use default */
00539 #ifndef _WIN32
00540 #ifdef LDAP_DEBUG
00541        ldap_debug = LDAP_DEBUG_ANY;
00542 #endif
00543 #endif
00544 
00545        while (( c = getopt( argc, argv, "uh:d:s:p:t:T:V:" )) != -1 ) {
00546               switch( c ) {
00547               case 'u':
00548 #ifdef CLDAP
00549                      cldapflg++;
00550 #else /* CLDAP */
00551                      printf( "Compile with -DCLDAP for UDP support\n" );
00552 #endif /* CLDAP */
00553                      break;
00554 
00555               case 'd':
00556 #ifndef _WIN32
00557 #ifdef LDAP_DEBUG
00558                      ldap_debug = atoi( optarg ) | LDAP_DEBUG_ANY;
00559                      if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
00560                             ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL,
00561                                    &ldap_debug );
00562                      }
00563 #else
00564                      printf( "Compile with -DLDAP_DEBUG for debugging\n" );
00565 #endif
00566 #endif
00567                      break;
00568 
00569               case 'h':
00570                      host = optarg;
00571                      break;
00572 
00573               case 's':
00574                      dnsuffix = optarg;
00575                      break;
00576 
00577               case 'p':
00578                      port = atoi( optarg );
00579                      break;
00580 
00581 #if !defined(MACOS) && !defined(DOS)
00582               case 't':     /* copy ber's to given file */
00583                      copyfname = strdup( optarg );
00584                      copyoptions = LBER_SOCKBUF_OPT_TO_FILE;
00585                      break;
00586 
00587               case 'T':     /* only output ber's to given file */
00588                      copyfname = strdup( optarg );
00589                      copyoptions = (LBER_SOCKBUF_OPT_TO_FILE |
00590                          LBER_SOCKBUF_OPT_TO_FILE_ONLY);
00591                      break;
00592 #endif
00593               case 'V':     /* LDAP protocol version */
00594                      ldapversion = atoi( optarg );
00595                      break;
00596 
00597               default:
00598                   ++errflg;
00599               }
00600        }
00601 
00602        if ( host == NULL && optind == argc - 1 ) {
00603               host = argv[ optind ];
00604               ++optind;
00605        }
00606 
00607        if ( errflg || optind < argc - 1 ) {
00608               fprintf( stderr, usage, argv[ 0 ] );
00609               exit( 1 );
00610        }
00611        
00612        printf( "%sldap_init( %s, %d )\n", cldapflg ? "c" : "",
00613               host == NULL ? "(null)" : host, port );
00614 
00615        if ( cldapflg ) {
00616 #ifdef CLDAP
00617               ld = cldap_open( host, port );
00618 #endif /* CLDAP */
00619        } else {
00620               ld = ldap_init( host, port );
00621        }
00622 
00623        if ( ld == NULL ) {
00624               perror( "ldap_init" );
00625               exit(1);
00626        }
00627 
00628        if ( ldapversion != 0 && ldap_set_option( ld,
00629            LDAP_OPT_PROTOCOL_VERSION, (void *)&ldapversion ) != 0 ) {
00630               ldap_perror( ld, "ldap_set_option (protocol version)" );
00631               exit(1);
00632        }
00633 
00634 #ifdef notdef
00635 #if !defined(MACOS) && !defined(DOS)
00636        if ( copyfname != NULL ) {
00637               int    fd;
00638               Sockbuf       *sb;
00639 
00640               if ( (fd = open( copyfname, O_WRONLY | O_CREAT, 0600 ))
00641                   == -1 ) {
00642                      perror( copyfname );
00643                      exit ( 1 );
00644               }
00645               ldap_get_option( ld, LDAP_OPT_SOCKBUF, &sb );
00646               ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_COPYDESC,
00647                   (void *) &fd );
00648               ber_sockbuf_set_option( sb, copyoptions, LBER_OPT_ON );
00649        }
00650 #endif
00651 #endif
00652 
00653        bound = 0;
00654        timeout.tv_sec = 0;
00655        timeout.tv_usec = 0;
00656        tvp = &timeout;
00657 
00658        (void) memset( line, '\0', sizeof(line) );
00659        while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) {
00660               command1 = line[0];
00661               command2 = line[1];
00662               command3 = line[2];
00663 
00664               switch ( command1 ) {
00665               case 'a':     /* add or abandon */
00666                      switch ( command2 ) {
00667                      case 'd':     /* add */
00668                             getline( dn, sizeof(dn), stdin, "dn? " );
00669                             strcat( dn, dnsuffix );
00670                             if ( (attrs = get_modlist( NULL, "attr? ",
00671                                 "value? " )) == NULL )
00672                                    break;
00673                             if ( (id = ldap_add( ld, dn, attrs )) == -1 )
00674                                    ldap_perror( ld, "ldap_add" );
00675                             else
00676                                    printf( "Add initiated with id %d\n",
00677                                        id );
00678                             break;
00679 
00680                      case 'b':     /* abandon */
00681                             getline( line, sizeof(line), stdin, "msgid? " );
00682                             id = atoi( line );
00683                             if ( ldap_abandon( ld, id ) != 0 )
00684                                    ldap_perror( ld, "ldap_abandon" );
00685                             else
00686                                    printf( "Abandon successful\n" );
00687                             break;
00688                      default:
00689                             printf( "Possibilities: [ad]d, [ab]ort\n" );
00690                      }
00691                      break;
00692 
00693               case 'v':     /* ldap protocol version */
00694                      getline( line, sizeof(line), stdin,
00695                          "ldap version? " );
00696                      version = atoi( line );
00697                      if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
00698                          (void *) &version ) != 0 ) {
00699                             ldap_perror( ld, "ldap_set_option" );
00700                      }
00701                      break;
00702 
00703               case 'b':     /* asynch bind */
00704                      getline( line, sizeof(line), stdin,
00705                          "method 0->simple 3->sasl? " );
00706                      method = atoi( line );
00707                      if ( method == 0 ) {
00708                             method = LDAP_AUTH_SIMPLE;
00709                      } else if ( method == 3 ) {
00710                             method = LDAP_AUTH_SASL;
00711                      }
00712                      getline( dn, sizeof(dn), stdin, "dn? " );
00713                      strcat( dn, dnsuffix );
00714 
00715                      if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
00716                      } else {
00717                             passwd[0] = '\0';
00718                      }
00719 
00720                      if ( method == LDAP_AUTH_SIMPLE ) {
00721                             if ( dn[0] != '\0' ) {
00722                                    getline( passwd, sizeof(passwd), stdin,
00723                                        "password? " );
00724                             } else {
00725                                    passwd[0] = '\0';
00726                             }
00727                             rc = ldap_simple_bind( ld, dn, passwd );
00728                      } else {
00729                             struct berval cred;
00730                             char          mechanism[BUFSIZ];
00731 
00732                             getline( mechanism, sizeof(mechanism), stdin,
00733                                 "mechanism? " );
00734                             getline( passwd, sizeof(passwd), stdin,
00735                                 "credentials? " );
00736                             cred.bv_val = passwd;
00737                             cred.bv_len = strlen( passwd );
00738                             if ( ldap_sasl_bind( ld, dn, mechanism, &cred,
00739                                 NULL, NULL, &rc ) != LDAP_SUCCESS ) {
00740                                    rc = -1;
00741                             }
00742                      }
00743                      if ( rc == -1 ) {
00744                             fprintf( stderr, "ldap_bind failed\n" );
00745                             ldap_perror( ld, "ldap_bind" );
00746                      } else {
00747                             printf( "Bind initiated\n" );
00748                             bound = 1;
00749                      }
00750                      break;
00751 
00752               case 'B':     /* synch bind */
00753                      getline( line, sizeof(line), stdin,
00754                          "method 0->simple 3->sasl? " );
00755                      method = atoi( line );
00756                      if ( method == 0 ) {
00757                             method = LDAP_AUTH_SIMPLE;
00758                      } else if ( method == 3 ) {
00759                             method = LDAP_AUTH_SASL;
00760                      }
00761                      getline( dn, sizeof(dn), stdin, "dn? " );
00762                      strcat( dn, dnsuffix );
00763 
00764                      if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
00765                      } else {
00766                             passwd[0] = '\0';
00767                      }
00768 
00769                      if ( method == LDAP_AUTH_SIMPLE ) {
00770                             if ( dn[0] != '\0' ) {
00771                                    getline( passwd, sizeof(passwd), stdin,
00772                                        "password? " );
00773                             } else {
00774                                    passwd[0] = '\0';
00775                             }
00776                             rc = ldap_simple_bind_s( ld, dn, passwd );
00777                             fnname = "ldap_simple_bind_s";
00778                      } else {
00779                             struct berval cred;
00780                             char          mechanism[BUFSIZ];
00781 
00782                             getline( mechanism, sizeof(mechanism), stdin,
00783                                 "mechanism? " );
00784                             getline( passwd, sizeof(passwd), stdin,
00785                                 "credentials? " );
00786                             cred.bv_val = passwd;
00787                             cred.bv_len = strlen( passwd );
00788                             rc = ldap_sasl_bind_s( ld, dn, mechanism,
00789                                    &cred, NULL, NULL, NULL );
00790                             fnname = "ldap_sasl_bind_s";
00791                      }
00792                      if ( rc != LDAP_SUCCESS ) {
00793                             fprintf( stderr, "%s failed\n", fnname );
00794                             ldap_perror( ld, fnname );
00795                      } else {
00796                             printf( "Bind successful\n" );
00797                             bound = 1;
00798                      }
00799                      break;
00800 
00801               case 'c':     /* compare */
00802                      getline( dn, sizeof(dn), stdin, "dn? " );
00803                      strcat( dn, dnsuffix );
00804                      getline( attr, sizeof(attr), stdin, "attr? " );
00805                      getline( value, sizeof(value), stdin, "value? " );
00806 
00807                      if ( (id = ldap_compare( ld, dn, attr, value )) == -1 )
00808                             ldap_perror( ld, "ldap_compare" );
00809                      else
00810                             printf( "Compare initiated with id %d\n", id );
00811                      break;
00812 
00813               case 'x':     /* extended operation */
00814                      {
00815                      char          oid[100];
00816                      struct berval val;
00817 
00818                      getline( oid, sizeof(oid), stdin, "oid? " );
00819                      getline( value, sizeof(value), stdin, "value? " );
00820 
00821                      val.bv_val = value;
00822                      val.bv_len = strlen( value );
00823                      if ( ldap_extended_operation( ld, oid, &val, NULL,
00824                          NULL, &id ) != LDAP_SUCCESS ) {
00825                             ldap_perror( ld, "ldap_extended_operation" );
00826                      } else {
00827                             printf( "Extended op initiated with id %d\n",
00828                                 id );
00829                      }
00830                      }
00831                      break;
00832 
00833               case 'C':     /* set cache parameters */
00834 #ifdef NO_LIBLCACHE
00835                      getline( line, sizeof(line), stdin,
00836                          "cache init (memcache 0)? " );
00837 #else
00838                      getline( line, sizeof(line), stdin,
00839                          "cache init (memcache 0, lcache 1)? " );
00840 #endif
00841                      i = atoi( line );
00842                      if ( i == 0 ) {             /* memcache */
00843                             unsigned long ttl, size;
00844                             char          **basedns, *dnarray[2];
00845                             LDAPMemCache  *mc;
00846 
00847                             getline( line, sizeof(line), stdin,
00848                                 "memcache ttl? " );
00849                             ttl = atoi( line );
00850                             getline( line, sizeof(line), stdin,
00851                                 "memcache size? " );
00852                             size = atoi( line );
00853                             getline( line, sizeof(line), stdin,
00854                                 "memcache baseDN? " );
00855                             if ( *line == '\0' ) {
00856                                    basedns = NULL;
00857                             } else {
00858                                    dnarray[0] = line;
00859                                    dnarray[1] = NULL;
00860                                    basedns = dnarray;
00861                             }
00862                             if (( rc = ldap_memcache_init( ttl, size,
00863                                 basedns, NULL, &mc )) != LDAP_SUCCESS ) {
00864                                    fprintf( stderr,
00865                                        "ldap_memcache_init: %s\n",
00866                                        ldap_err2string( rc ));
00867                             } else if (( rc = ldap_memcache_set( ld, mc ))
00868                                 != LDAP_SUCCESS ) {
00869                                    fprintf( stderr,
00870                                        "ldap_memcache_set: %s\n",
00871                                        ldap_err2string( rc ));
00872                             }
00873 
00874 #ifndef NO_LIBLCACHE
00875                      } else if ( i == 1 ) {
00876                             getline( line, sizeof(line), stdin,
00877                                 "cache config file? " );
00878                             if ( line[0] != '\0' ) {
00879                                    if ( lcache_init( ld, line ) != 0 ) {
00880                                           perror( "ldap_cache_init" );
00881                                           break;
00882                                    }
00883                             }
00884                             getline( line, sizeof(line), stdin,
00885                                 "cache on/off (on 1, off 0)? " );
00886                             if ( line[0] != '\0' ) {
00887                                    i = atoi( line );
00888                                    if ( ldap_set_option( ld,
00889                                        LDAP_OPT_CACHE_ENABLE, &i ) != 0 ) {
00890                                           ldap_perror( ld, "ldap_cache_enable" );
00891                                           break;
00892                                    }
00893                             }
00894                             getline( line, sizeof(line), stdin,
00895                               "cache strategy (check 0, populate 1, localdb 2)? " );
00896                             if ( line[0] != '\0' ) {
00897                                    i = atoi( line );
00898                                    if ( ldap_set_option( ld,
00899                                        LDAP_OPT_CACHE_STRATEGY, &i )
00900                                        != 0 ) {
00901                                           ldap_perror(ld, "ldap_cache_strategy");
00902                                           break;
00903                                    }
00904                             }
00905 #endif /* !NO_LIBLCACHE */
00906 
00907                      } else {
00908                             fprintf( stderr, "unknown cachetype %d\n", i );
00909                      }
00910                      break;
00911 
00912               case 'd':     /* turn on debugging */
00913 #ifndef _WIN32
00914 #ifdef LDAP_DEBUG
00915                      getline( line, sizeof(line), stdin, "debug level? " );
00916                      ldap_debug = atoi( line ) | LDAP_DEBUG_ANY;
00917                      if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
00918                             ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL,
00919                                    &ldap_debug );
00920                      }
00921 #else
00922                      printf( "Compile with -DLDAP_DEBUG for debugging\n" );
00923 #endif
00924 #endif
00925                      break;
00926 
00927               case 'E':     /* explode a dn */
00928                      getline( line, sizeof(line), stdin, "dn? " );
00929                      exdn = ldap_explode_dn( line, 0 );
00930                      for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) {
00931                             printf( "\t\"%s\"\n", exdn[i] );
00932                      }
00933                      break;
00934 
00935               case 'R':     /* explode an rdn */
00936                      getline( line, sizeof(line), stdin, "rdn? " );
00937                      exdn = ldap_explode_rdn( line, 0 );
00938                      for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) {
00939                             printf( "\t\"%s\"\n", exdn[i] );
00940                      }
00941                      break;
00942 
00943               case 'm':     /* modify or modifyrdn */
00944                      if ( strncmp( line, "modify", 4 ) == 0 ) {
00945                             getline( dn, sizeof(dn), stdin, "dn? " );
00946                             strcat( dn, dnsuffix );
00947                             if ( (mods = get_modlist(
00948                                 "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ",
00949                                 "attribute type? ", "attribute value? " ))
00950                                 == NULL )
00951                                    break;
00952                             if ( (id = ldap_modify( ld, dn, mods )) == -1 )
00953                                    ldap_perror( ld, "ldap_modify" );
00954                             else
00955                                    printf( "Modify initiated with id %d\n",
00956                                        id );
00957                      } else if ( strncmp( line, "modrdn", 4 ) == 0 ) {
00958                             getline( dn, sizeof(dn), stdin, "dn? " );
00959                             strcat( dn, dnsuffix );
00960                             getline( rdn, sizeof(rdn), stdin, "newrdn? " );
00961                             getline( line, sizeof(line), stdin,
00962                                 "deleteoldrdn? " );
00963                             if ( (id = ldap_modrdn2( ld, dn, rdn,
00964                                 atoi(line) )) == -1 )
00965                                    ldap_perror( ld, "ldap_modrdn" );
00966                             else
00967                                    printf( "Modrdn initiated with id %d\n",
00968                                        id );
00969                      } else {
00970                             printf( "Possibilities: [modi]fy, [modr]dn\n" );
00971                      }
00972                      break;
00973 
00974               case 'q':     /* quit */
00975 #ifdef CLDAP
00976                      if ( cldapflg )
00977                             cldap_close( ld );
00978 #endif /* CLDAP */
00979                      if ( !cldapflg )
00980                             ldap_unbind( ld );
00981                      exit( 0 );
00982                      break;
00983 
00984               case 'r':     /* result or remove */
00985                      switch ( command3 ) {
00986                      case 's':     /* result */
00987                             getline( line, sizeof(line), stdin,
00988                                 "msgid (-1=>any)? " );
00989                             if ( line[0] == '\0' )
00990                                    id = -1;
00991                             else
00992                                    id = atoi( line );
00993                             getline( line, sizeof(line), stdin,
00994                                 "all (0=>any, 1=>all)? " );
00995                             if ( line[0] == '\0' )
00996                                    all = 1;
00997                             else
00998                                    all = atoi( line );
00999                             if (( msgtype = ldap_result( ld, id, all,
01000                                 tvp, &res )) < 1 ) {
01001                                    ldap_perror( ld, "ldap_result" );
01002                                    break;
01003                             }
01004                             printf( "\nresult: msgtype %d msgid %d\n",
01005                                 msgtype, ldap_msgid( res ) );
01006                             handle_result( ld, res, 0 );
01007                             res = NULL;
01008                             break;
01009 
01010                      case 'm':     /* remove */
01011                             getline( dn, sizeof(dn), stdin, "dn? " );
01012                             strcat( dn, dnsuffix );
01013                             if ( (id = ldap_delete( ld, dn )) == -1 )
01014                                    ldap_perror( ld, "ldap_delete" );
01015                             else
01016                                    printf( "Remove initiated with id %d\n",
01017                                        id );
01018                             break;
01019 
01020                      default:
01021                             printf( "Possibilities: [rem]ove, [res]ult\n" );
01022                             break;
01023                      }
01024                      break;
01025 
01026               case 's':     /* search */
01027                      getline( dn, sizeof(dn), stdin, "searchbase? " );
01028                      strcat( dn, dnsuffix );
01029                      getline( line, sizeof(line), stdin,
01030                          "scope (0=Base, 1=One Level, 2=Subtree)? " );
01031                      scope = atoi( line );
01032                      getline( filter, sizeof(filter), stdin,
01033                          "search filter (e.g. sn=jones)? " );
01034                      types = get_list( "attrs to return? " );
01035                      getline( line, sizeof(line), stdin,
01036                          "attrsonly (0=attrs&values, 1=attrs only)? " );
01037                      attrsonly = atoi( line );
01038 
01039                      if ( cldapflg ) {
01040 #ifdef CLDAP
01041                          getline( line, sizeof(line), stdin,
01042                             "Requestor DN (for logging)? " );
01043                          if ( cldap_search_s( ld, dn, scope, filter, types,
01044                                 attrsonly, &res, line ) != 0 ) {
01045                             ldap_perror( ld, "cldap_search_s" );
01046                          } else {
01047                             printf( "\nresult: msgid %d\n",
01048                                 res->lm_msgid );
01049                             handle_result( ld, res, 0 );
01050                             res = NULL;
01051                          }
01052 #endif /* CLDAP */
01053                      } else {
01054                          if (( id = ldap_search( ld, dn, scope, filter,
01055                                 types, attrsonly  )) == -1 ) {
01056                             ldap_perror( ld, "ldap_search" );
01057                          } else {
01058                             printf( "Search initiated with id %d\n", id );
01059                          }
01060                      }
01061                      free_list( types );
01062                      break;
01063 
01064               case 't':     /* set timeout value */
01065                      getline( line, sizeof(line), stdin, "timeout (-1=infinite)? " );
01066                      timeout.tv_sec = atoi( line );
01067                      if ( timeout.tv_sec < 0 ) {
01068                             tvp = NULL;
01069                      } else {
01070                             tvp = &timeout;
01071                      }
01072                      break;
01073 
01074               case 'U':     /* set ufn search prefix */
01075                      getline( line, sizeof(line), stdin, "ufn prefix? " );
01076                      ldap_ufn_setprefix( ld, line );
01077                      break;
01078 
01079               case 'u':     /* user friendly search w/optional timeout */
01080                      getline( dn, sizeof(dn), stdin, "ufn? " );
01081                      strcat( dn, dnsuffix );
01082                      types = get_list( "attrs to return? " );
01083                      getline( line, sizeof(line), stdin,
01084                          "attrsonly (0=attrs&values, 1=attrs only)? " );
01085                      attrsonly = atoi( line );
01086 
01087                      if ( command2 == 't' ) {
01088                             id = ldap_ufn_search_c( ld, dn, types,
01089                                 attrsonly, &res, ldap_ufn_timeout,
01090                                 &timeout );
01091                      } else {
01092                             id = ldap_ufn_search_s( ld, dn, types,
01093                                 attrsonly, &res );
01094                      }
01095                      if ( res == NULL )
01096                             ldap_perror( ld, "ldap_ufn_search" );
01097                      else {
01098                             printf( "\nresult: err %d\n", id );
01099                             handle_result( ld, res, 0 );
01100                             res = NULL;
01101                      }
01102                      free_list( types );
01103                      break;
01104 
01105               case 'l':     /* URL search */
01106                      getline( line, sizeof(line), stdin,
01107                          "attrsonly (0=attrs&values, 1=attrs only)? " );
01108                      attrsonly = atoi( line );
01109                      getline( line, sizeof(line), stdin, "LDAP URL? " );
01110                      if (( id = ldap_url_search( ld, line, attrsonly  ))
01111                             == -1 ) {
01112                          ldap_perror( ld, "ldap_url_search" );
01113                      } else {
01114                          printf( "URL search initiated with id %d\n", id );
01115                      }
01116                      break;
01117 
01118               case 'p':     /* parse LDAP URL */
01119                      getline( line, sizeof(line), stdin, "LDAP URL? " );
01120                      if (( i = ldap_url_parse( line, &ludp )) != 0 ) {
01121                          fprintf( stderr, "ldap_url_parse: error %d (%s)\n", i,
01122                                           url_parse_err2string( i ));
01123                      } else {
01124                          printf( "\t  host: " );
01125                          if ( ludp->lud_host == NULL ) {
01126                             printf( "DEFAULT\n" );
01127                          } else {
01128                             printf( "<%s>\n", ludp->lud_host );
01129                          }
01130                          printf( "\t  port: " );
01131                          if ( ludp->lud_port == 0 ) {
01132                             printf( "DEFAULT\n" );
01133                          } else {
01134                             printf( "%d\n", ludp->lud_port );
01135                          }
01136                          printf( "\tsecure: %s\n", ( ludp->lud_options &
01137                                 LDAP_URL_OPT_SECURE ) != 0 ? "Yes" : "No" );
01138                          printf( "\t    dn: " );
01139                          if ( ludp->lud_dn == NULL ) {
01140                             printf( "ROOT\n" );
01141                          } else {
01142                             printf( "%s\n", ludp->lud_dn );
01143                          }
01144                          printf( "\t attrs:" );
01145                          if ( ludp->lud_attrs == NULL ) {
01146                             printf( " ALL" );
01147                          } else {
01148                             for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) {
01149                                 printf( " <%s>", ludp->lud_attrs[ i ] );
01150                             }
01151                          }
01152                          printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_ONELEVEL ?
01153                             "ONE" : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" :
01154                             ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" : "**invalid**" );
01155                          printf( "\tfilter: <%s>\n", ludp->lud_filter );
01156                          ldap_free_urldesc( ludp );
01157                      }
01158                          break;
01159 
01160               case 'n':     /* set dn suffix, for convenience */
01161                      getline( line, sizeof(line), stdin, "DN suffix? " );
01162                      strcpy( dnsuffix, line );
01163                      break;
01164 
01165               case 'N':     /* add an LDAPv3 control */
01166                      getline( line, sizeof(line), stdin,
01167                          "Control oid (. to clear list)? " );
01168                      if ( *line == '.' && *(line+1) == '\0' ) {
01169                          controls = NULL;
01170                      } else {
01171                          newctrl = (LDAPControl *) malloc(
01172                             sizeof(LDAPControl) );
01173                          newctrl->ldctl_oid = strdup( line );
01174                          getline( line, sizeof(line), stdin,
01175                             "Control value? " );
01176                          if ( strncmp( line, "0x", 2 ) == 0 ) {
01177                                 newctrl->ldctl_value.bv_val =
01178                                 (char *)malloc( strlen( line ) / 2 );
01179                                 berval_from_hex( &(newctrl->ldctl_value), 
01180                                        line + 2 );
01181                          } else {
01182                                 newctrl->ldctl_value.bv_val
01183                                    = strdup( line );
01184                          }
01185                          newctrl->ldctl_value.bv_len = strlen( line );
01186                          getline( line, sizeof(line), stdin,
01187                             "Critical (0=no, 1=yes)? " );
01188                          newctrl->ldctl_iscritical = atoi( line );
01189                          add_control( &controls, newctrl );
01190                      }
01191                      ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS,
01192                          controls );
01193                      ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS,
01194                          &tmpctrls );
01195                      print_controls( tmpctrls, 0 );
01196                      break;
01197 
01198               case 'P':     /* add a persistent search control */
01199                      getline( line, sizeof(line), stdin, "Changetypes to "
01200                          " return (additive - add (1), delete (2), "
01201                          "modify (4), modDN (8))? " );
01202                      changetypes = atoi(line);
01203                      getline( line, sizeof(line), stdin,
01204                          "Return changes only (0=no, 1=yes)? " );
01205                      changesonly = atoi(line);
01206                      getline( line, sizeof(line), stdin, "Return entry "
01207                          "change controls (0=no, 1=yes)? " );
01208                      return_echg_ctls = atoi(line);
01209                      getline( line, sizeof(line), stdin,
01210                             "Critical (0=no, 1=yes)? " );
01211                      if ( ldap_create_persistentsearch_control( ld,
01212                          changetypes, changesonly, return_echg_ctls,
01213                          (char)atoi(line), &newctrl ) != LDAP_SUCCESS ) {
01214                             ldap_perror( ld, "ldap_create_persistent"
01215                                 "search_control" );
01216                      } else {
01217                          add_control( &controls, newctrl );
01218                          ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS,
01219                             controls );
01220                          ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS,
01221                             &tmpctrls );
01222                          print_controls( tmpctrls, 0 );
01223                      }
01224                      break;
01225                      
01226               case 'o':     /* set ldap options */
01227                      getline( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" );
01228                      i = atoi( line );
01229                      ldap_set_option( ld, LDAP_OPT_DEREF, &i );
01230                      getline( line, sizeof(line), stdin, "timelimit?" );
01231                      i = atoi( line );
01232                      ldap_set_option( ld, LDAP_OPT_TIMELIMIT, &i );
01233                      getline( line, sizeof(line), stdin, "sizelimit?" );
01234                      i = atoi( line );
01235                      ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &i );
01236 
01237 #ifdef STR_TRANSLATION
01238                      getline( line, sizeof(line), stdin,
01239                             "Automatic translation of T.61 strings (0=no, 1=yes)?" );
01240                      if ( atoi( line ) == 0 ) {
01241                             ld->ld_lberoptions &= ~LBER_OPT_TRANSLATE_STRINGS;
01242                      } else {
01243                             ld->ld_lberoptions |= LBER_OPT_TRANSLATE_STRINGS;
01244 #ifdef LDAP_CHARSET_8859
01245                             getline( line, sizeof(line), stdin,
01246                                    "Translate to/from ISO-8859 (0=no, 1=yes?" );
01247                             if ( atoi( line ) != 0 ) {
01248                                    ldap_set_string_translators( ld,
01249                                        ldap_8859_to_t61,
01250                                        ldap_t61_to_8859 );
01251                             }
01252 #endif /* LDAP_CHARSET_8859 */
01253                      }
01254 #endif /* STR_TRANSLATION */
01255 
01256 #ifdef LDAP_DNS
01257                      getline( line, sizeof(line), stdin,
01258                             "Use DN & DNS to determine where to send requests (0=no, 1=yes)?" );
01259                      optval = ( atoi( line ) != 0 );
01260                      ldap_set_option( ld, LDAP_OPT_DNS, (void *) optval );
01261 #endif /* LDAP_DNS */
01262 
01263                      getline( line, sizeof(line), stdin,
01264                             "Recognize and chase referrals (0=no, 1=yes)?" );
01265                      optval = ( atoi( line ) != 0 );
01266                      ldap_set_option( ld, LDAP_OPT_REFERRALS,
01267                          (void *) optval );
01268                      if ( optval ) {
01269                             getline( line, sizeof(line), stdin,
01270                                    "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" );
01271                             if ( atoi( line ) != 0 ) {
01272                                    ldap_set_rebind_proc( ld, bind_prompt,
01273                                        NULL );
01274                             }
01275                      }
01276 #ifdef NET_SSL
01277                      getline( line, sizeof(line), stdin,
01278                             "Use Secure Sockets Layer - SSL (0=no, 1=yes)?" );
01279                      optval = ( atoi( line ) != 0 );
01280                      if ( optval ) {
01281                             getline( line, sizeof(line), stdin,
01282                                 "security DB path?" ); 
01283                             if ( ldapssl_client_init( (*line == '\0') ?
01284                                 NULL : line, &certdbhandle ) < 0 ) {
01285                                    perror( "ldapssl_client_init" );
01286                                    optval = 0;     /* SSL not avail. */
01287                             } else if ( ldapssl_install_routines( ld )
01288                                 < 0 ) {
01289                                    ldap_perror( ld,
01290                                        "ldapssl_install_routines" );
01291                                    optval = 0;     /* SSL not avail. */
01292                             }
01293                      }
01294 
01295                      ldap_set_option( ld, LDAP_OPT_SSL,
01296                          optval ? LDAP_OPT_ON : LDAP_OPT_OFF );
01297 #endif
01298 
01299                      getline( line, sizeof(line), stdin, "Reconnect?" );
01300                      ldap_set_option( ld, LDAP_OPT_RECONNECT,
01301                          ( atoi( line ) == 0 ) ? LDAP_OPT_OFF :
01302                          LDAP_OPT_ON );
01303                      break;
01304 
01305               case 'I':     /* initialize display templates */
01306                      getline( line, sizeof(line), stdin,       
01307                             "Template file [ldaptemplates.conf]?" );
01308                      if (( i = ldap_init_templates( *line == '\0' ?
01309                             "ldaptemplates.conf" : line, &tmpllist ))
01310                             != 0 ) {
01311                          fprintf( stderr, "ldap_init_templates: %s\n",
01312                                 ldap_tmplerr2string( i ));
01313                      }
01314                      break;
01315 
01316               case 'T':     /* read & display using template */
01317                      getline( dn, sizeof(dn), stdin, "entry DN? " );
01318                      strcat( dn, dnsuffix );
01319                      if (( i = ldap_entry2text_search( ld, dn, NULL, NULL,
01320                             tmpllist, NULL, NULL, entry2textwrite, stdout,
01321                             "\n", 0, 0 )) != LDAP_SUCCESS ) {
01322                          fprintf( stderr, "ldap_entry2text_search: %s\n",
01323                                 ldap_err2string( i ));
01324                      }
01325                      break;
01326 
01327               case 'L':     /* set preferred language */
01328                      getline( line, sizeof(line), stdin,
01329                             "Preferred language? " );
01330                      if ( *line == '\0' ) {
01331                             ldap_set_option( ld,
01332                                 LDAP_OPT_PREFERRED_LANGUAGE, NULL );
01333                      } else {
01334                             ldap_set_option( ld,
01335                                 LDAP_OPT_PREFERRED_LANGUAGE, line );
01336                      }
01337                      break;
01338 
01339               case 'F':     /* create filter */
01340                      {
01341                             char   filtbuf[ 512 ], pattern[ 512 ];
01342                             char   prefix[ 512 ], suffix[ 512 ];
01343                             char   attr[ 512 ], value[ 512 ];
01344                             char   *dupvalue, **words;
01345 
01346                             getline( pattern, sizeof(pattern), stdin,
01347                                 "pattern? " );
01348                             getline( prefix, sizeof(prefix), stdin,
01349                                 "prefix? " );
01350                             getline( suffix, sizeof(suffix), stdin,
01351                                 "suffix? " );
01352                             getline( attr, sizeof(attr), stdin,
01353                                 "attribute? " );
01354                             getline( value, sizeof(value), stdin,
01355                                 "value? " );
01356                             
01357                             if (( dupvalue = strdup( value )) != NULL ) {
01358                                    words = string2words( value, " " );
01359                             } else {
01360                                    words = NULL;
01361                             }
01362                             if ( ldap_create_filter( filtbuf,
01363                                 sizeof(filtbuf), pattern, prefix, suffix,
01364                                 attr, value, words) != 0 ) {
01365                                    fprintf( stderr,
01366                                           "ldap_create_filter failed\n" );
01367                             } else {
01368                                    printf( "filter is \"%s\"\n", filtbuf );
01369                             }
01370                             if ( dupvalue != NULL ) free( dupvalue );
01371                             if ( words != NULL ) free( words );
01372                      }
01373                      break;
01374 
01375               case '?':     /* help */
01376               case '\0':    /* help */
01377     printf( "Commands: [ad]d         [ab]andon         [b]ind\n" );
01378     printf( "          synch [B]ind  [c]ompare         [l]URL search\n" );
01379     printf( "          [modi]fy      [modr]dn          [rem]ove\n" );
01380     printf( "          [res]ult      [s]earch          [q]uit/unbind\n\n" );
01381     printf( "          [u]fn search  [ut]fn search with timeout\n" );
01382     printf( "          [d]ebug       [C]set cache parms[g]set msgid\n" );
01383     printf( "          d[n]suffix    [t]imeout         [v]ersion\n" );
01384     printf( "          [U]fn prefix  [?]help           [o]ptions\n" );
01385     printf( "          [E]xplode dn  [p]arse LDAP URL  [R]explode RDN\n" );
01386     printf( "          e[x]tended op [F]ilter create\n" );
01387     printf( "          set co[N]trols    set preferred [L]anguage\n" );
01388     printf( "          add a [P]ersistent search control\n" );
01389     printf( "          [I]nitialize display templates\n" );
01390     printf( "          [T]read entry and display using template\n" );
01391                      break;
01392 
01393               default:
01394                      printf( "Invalid command.  Type ? for help.\n" );
01395                      break;
01396               }
01397 
01398               (void) memset( line, '\0', sizeof(line) );
01399        }
01400 
01401        return( 0 );
01402 }
01403 
01404 static void
01405 handle_result( LDAP *ld, LDAPMessage *lm, int onlyone )
01406 {
01407        int    msgtype;
01408 
01409        switch ( (msgtype = ldap_msgtype( lm )) ) {
01410        case LDAP_RES_COMPARE:
01411               printf( "Compare result\n" );
01412               print_ldap_result( ld, lm, "compare" );
01413               break;
01414 
01415        case LDAP_RES_SEARCH_RESULT:
01416               printf( "Search result\n" );
01417               print_ldap_result( ld, lm, "search" );
01418               break;
01419 
01420        case LDAP_RES_SEARCH_ENTRY:
01421               printf( "Search entry\n" );
01422               print_search_entry( ld, lm, onlyone );
01423               break;
01424 
01425        case LDAP_RES_SEARCH_REFERENCE:
01426               printf( "Search reference\n" );
01427               print_search_reference( ld, lm, onlyone );
01428               break;
01429 
01430        case LDAP_RES_ADD:
01431               printf( "Add result\n" );
01432               print_ldap_result( ld, lm, "add" );
01433               break;
01434 
01435        case LDAP_RES_DELETE:
01436               printf( "Delete result\n" );
01437               print_ldap_result( ld, lm, "delete" );
01438               break;
01439 
01440        case LDAP_RES_MODIFY:
01441               printf( "Modify result\n" );
01442               print_ldap_result( ld, lm, "modify" );
01443               break;
01444 
01445        case LDAP_RES_MODRDN:
01446               printf( "ModRDN result\n" );
01447               print_ldap_result( ld, lm, "modrdn" );
01448               break;
01449 
01450        case LDAP_RES_BIND:
01451               printf( "Bind result\n" );
01452               print_ldap_result( ld, lm, "bind" );
01453               break;
01454        case LDAP_RES_EXTENDED:
01455               if ( ldap_msgid( lm ) == LDAP_RES_UNSOLICITED ) {
01456                      printf( "Unsolicited result\n" );
01457                      print_ldap_result( ld, lm, "unsolicited" );
01458               } else {
01459                      printf( "ExtendedOp result\n" );
01460                      print_ldap_result( ld, lm, "extendedop" );
01461               }
01462               break;
01463 
01464        default:
01465               printf( "Unknown result type 0x%x\n", msgtype );
01466               print_ldap_result( ld, lm, "unknown" );
01467        }
01468 
01469        if ( !onlyone ) {
01470               ldap_msgfree( lm );
01471        }
01472 }
01473 
01474 static void
01475 print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s )
01476 {
01477        int           lderr;
01478        char          *matcheddn, *errmsg, *oid, **refs;
01479        LDAPControl   **ctrls;
01480        struct berval *servercred, *data;
01481 
01482        if ( ldap_parse_result( ld, lm, &lderr, &matcheddn, &errmsg, &refs,
01483            &ctrls, 0 ) != LDAP_SUCCESS ) {
01484               ldap_perror( ld, "ldap_parse_result" );
01485        } else {
01486               fprintf( stderr, "%s: %s", s, ldap_err2string( lderr ));
01487               if ( lderr == LDAP_CONNECT_ERROR ) {
01488                      perror( " - " );
01489               } else {
01490                      fputc( '\n', stderr );
01491               }
01492               if ( errmsg != NULL ) {
01493                      if ( *errmsg != '\0' ) {
01494                             fprintf( stderr, "Additional info: %s\n",
01495                                 errmsg );
01496                      }
01497                      ldap_memfree( errmsg );
01498               }
01499               if ( matcheddn != NULL ) {
01500                      if ( NAME_ERROR( lderr )) {
01501                             fprintf( stderr, "Matched DN: %s\n",
01502                                 matcheddn );
01503                      }
01504                      ldap_memfree( matcheddn );
01505               }
01506               print_referrals( refs, 1 );
01507               print_controls( ctrls, 1 );
01508        }
01509 
01510        /* if SASL bind response, get and show server credentials */
01511        if ( ldap_msgtype( lm ) == LDAP_RES_BIND &&
01512            ldap_parse_sasl_bind_result( ld, lm, &servercred, 0 ) ==
01513            LDAP_SUCCESS && servercred != NULL ) {
01514               fputs( "\tSASL server credentials:\n", stderr );
01515               bprint( servercred->bv_val, servercred->bv_len );
01516               ber_bvfree( servercred );
01517        }
01518 
01519        /* if ExtendedOp response, get and show oid plus data */
01520        if ( ldap_msgtype( lm ) == LDAP_RES_EXTENDED &&
01521            ldap_parse_extended_result( ld, lm, &oid, &data, 0 ) ==
01522            LDAP_SUCCESS ) {
01523               if ( oid != NULL ) {
01524                      if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION )
01525                          == 0 ) {
01526                             printf(
01527                                 "\t%s Notice of Disconnection (OID: %s)\n",
01528                                 s, oid );
01529                      } else {
01530                             printf( "\t%s OID: %s\n", s, oid );
01531                      }
01532                      ldap_memfree( oid );
01533               }
01534               if ( data != NULL ) {
01535                      printf( "\t%s data:\n", s );
01536                      bprint( data->bv_val, data->bv_len );
01537                      ber_bvfree( data );
01538               }
01539        }
01540 }
01541 
01542 static void
01543 print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone )
01544 {
01545        BerElement    *ber;
01546        char          *a, *dn, *ufn;
01547        struct berval **vals;
01548        int           i, count;
01549        LDAPMessage   *e, *msg;
01550        LDAPControl   **ectrls;
01551 
01552        count = 0;
01553        for ( msg = ldap_first_message( ld, res );
01554            msg != NULL && ( !onlyone || count == 0 );
01555            msg = ldap_next_message( ld, msg ), ++count ) {
01556               if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) {
01557                   handle_result( ld, msg, 1 );   /* something else */
01558                   continue;
01559               }
01560               e = msg;
01561 
01562               dn = ldap_get_dn( ld, e );
01563               printf( "\tDN: %s\n", dn );
01564 
01565               ufn = ldap_dn2ufn( dn );
01566               printf( "\tUFN: %s\n", ufn );
01567 #ifdef WINSOCK
01568               ldap_memfree( dn );
01569               ldap_memfree( ufn );
01570 #else /* WINSOCK */
01571               free( dn );
01572               free( ufn );
01573 #endif /* WINSOCK */
01574 
01575               for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
01576                   a = ldap_next_attribute( ld, e, ber ) ) {
01577                      printf( "\t\tATTR: %s\n", a );
01578                      if ( (vals = ldap_get_values_len( ld, e, a ))
01579                          == NULL ) {
01580                             printf( "\t\t\t(no values)\n" );
01581                      } else {
01582                             for ( i = 0; vals[i] != NULL; i++ ) {
01583                                    int           nonascii = 0;
01584                                    unsigned long j;
01585 
01586                                    for ( j = 0; j < vals[i]->bv_len; j++ )
01587                                           if ( !isascii( vals[i]->bv_val[j] ) ) {
01588                                                  nonascii = 1;
01589                                                  break;
01590                                           }
01591 
01592                                    if ( nonascii ) {
01593                                           printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len );
01594 #ifdef BPRINT_NONASCII
01595                                           bprint( vals[i]->bv_val,
01596                                               vals[i]->bv_len );
01597 #endif /* BPRINT_NONASCII */
01598                                           continue;
01599                                    }
01600                                    printf( "\t\t\tlength (%ld) %s\n",
01601                                        vals[i]->bv_len, vals[i]->bv_val );
01602                             }
01603                             ber_bvecfree( vals );
01604                      }
01605                      ldap_memfree( a );
01606               }
01607               if ( ldap_get_lderrno( ld, NULL, NULL ) != LDAP_SUCCESS ) {
01608                      ldap_perror( ld,
01609                          "ldap_first_attribute/ldap_next_attribute" );
01610               }
01611               if ( ber != NULL ) {
01612                      ber_free( ber, 0 );
01613               }
01614 
01615               if ( ldap_get_entry_controls( ld, e, &ectrls )
01616                   != LDAP_SUCCESS ) {
01617                      ldap_perror( ld, "ldap_get_entry_controls" );
01618               } else {
01619                      int    changetype, changenumpresent;
01620                      char   *prevdn;
01621                      long   changenum;
01622 
01623                      if ( ldap_parse_entrychange_control( ld, ectrls,
01624                          &changetype, &prevdn, &changenumpresent,
01625                          &changenum ) == LDAP_SUCCESS ) {
01626                             fprintf( stderr, "EntryChangeNotification\n"
01627                                 "\tchangeType:   %s\n", 
01628                                 changetype_num2string( changetype ));
01629                             if ( prevdn != NULL ) {
01630                                    fprintf( stderr,
01631                                        "\tpreviousDN:   \"%s\"\n",
01632                                        prevdn );
01633                             }
01634                             if ( changenumpresent ) {
01635                                    fprintf( stderr, "\tchangeNumber: %d\n",
01636                                        changenum );
01637                             }
01638                             if ( prevdn != NULL ) {
01639                                    free( prevdn );
01640                             }
01641                      }
01642                      print_controls( ectrls, 1 );
01643               }
01644        }
01645 }
01646 
01647 
01648 static char *
01649 changetype_num2string( int chgtype )
01650 {
01651     static char buf[ 25 ];
01652     char      *s;
01653 
01654     switch( chgtype ) {
01655     case LDAP_CHANGETYPE_ADD:
01656        s = "add";
01657        break;
01658     case LDAP_CHANGETYPE_DELETE:
01659        s = "delete";
01660        break;
01661     case LDAP_CHANGETYPE_MODIFY:
01662        s = "modify";
01663        break;
01664     case LDAP_CHANGETYPE_MODDN:
01665        s = "moddn";
01666        break;
01667     default:
01668        s = buf;
01669        sprintf( s, "unknown (%d)", chgtype );
01670     }
01671 
01672     return( s );
01673 }
01674 
01675 
01676 static void
01677 print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone )
01678 {
01679        LDAPMessage   *msg;
01680        LDAPControl   **ctrls;
01681        char          **refs;
01682        int           count;
01683 
01684        count = 0;
01685        for ( msg = ldap_first_message( ld, res );
01686            msg != NULL && ( !onlyone || count == 0 );
01687            msg = ldap_next_message( ld, msg ), ++count ) {
01688               if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_REFERENCE ) {
01689                      handle_result( ld, msg, 1 );       /* something else */
01690                      continue;
01691               }
01692 
01693               if ( ldap_parse_reference( ld, msg, &refs, &ctrls, 0 ) !=
01694                   LDAP_SUCCESS ) {
01695                      ldap_perror( ld, "ldap_parse_reference" );
01696               } else {
01697                      print_referrals( refs, 1 );
01698                      print_controls( ctrls, 1 );
01699               }
01700        }
01701 }
01702 
01703 
01704 static void
01705 print_referrals( char **refs, int freeit )
01706 {
01707        int    i;
01708 
01709        if ( refs == NULL ) {
01710               return;
01711        }
01712 
01713        fprintf( stderr, "Referrals:\n" );
01714        for ( i = 0; refs[ i ] != NULL; ++i ) {
01715               fprintf( stderr, "\t%s\n", refs[ i ] );
01716        }
01717 
01718        if ( freeit ) {
01719               ldap_value_free( refs );
01720        }
01721 }
01722 
01723 
01724 static void
01725 print_controls( LDAPControl **ctrls, int freeit )
01726 {
01727        int    i;
01728 
01729        if ( ctrls == NULL ) {
01730               return;
01731        }
01732 
01733        fprintf( stderr, "Controls:\n" );
01734        for ( i = 0; ctrls[ i ] != NULL; ++i ) {
01735               if ( i > 0 ) {
01736                      fputs( "\t-----------\n", stderr );
01737               }
01738               fprintf( stderr, "\toid:      %s\n", ctrls[ i ]->ldctl_oid );
01739               fprintf( stderr, "\tcritical: %s\n",
01740                   ctrls[ i ]->ldctl_iscritical ? "YES" : "NO" );
01741               fputs( "\tvalue:\n", stderr );
01742               bprint( ctrls[ i ]->ldctl_value.bv_val,
01743                   ctrls[ i ]->ldctl_value.bv_len );
01744        }
01745 
01746        if ( freeit ) {
01747               ldap_controls_free( ctrls );
01748        }
01749 }
01750 
01751 
01752 static int
01753 entry2textwrite( void *fp, char *buf, int len )
01754 {
01755         return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len );
01756 }
01757 
01758 
01759 /* similar to getfilter.c:break_into_words() */
01760 static char **
01761 string2words( char *str, char *delims )
01762 {
01763     char        *word, **words;
01764     int         count;
01765     char        *lasts;
01766 
01767     if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) {
01768            return( NULL );
01769     }
01770     count = 0;
01771     words[ count ] = NULL;
01772 
01773     word = ldap_utf8strtok_r( str, delims, &lasts );
01774     while ( word != NULL ) {
01775         if (( words = (char **)realloc( words,
01776                 ( count + 2 ) * sizeof( char * ))) == NULL ) {
01777            free( words );
01778             return( NULL );
01779         }
01780 
01781         words[ count ] = word;
01782         words[ ++count ] = NULL;
01783         word = ldap_utf8strtok_r( NULL, delims, &lasts );
01784     }
01785 
01786     return( words );
01787 }
01788 
01789 
01790 static const char *
01791 url_parse_err2string( int e )
01792 {
01793     const char       *s = "unknown";
01794 
01795     switch( e ) {
01796     case LDAP_URL_ERR_NOTLDAP:
01797        s = "URL doesn't begin with \"ldap://\"";
01798        break;
01799     case LDAP_URL_ERR_NODN:
01800        s = "URL has no DN (required)";
01801        break;
01802     case LDAP_URL_ERR_BADSCOPE:
01803        s = "URL scope string is invalid";
01804        break;
01805     case LDAP_URL_ERR_MEM:
01806        s = "can't allocate memory space";
01807        break;
01808     case LDAP_URL_ERR_PARAM:
01809        s = "bad parameter to an URL function";
01810        break;
01811     case LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION:
01812        s = "unrecognized critical URL extension";
01813        break;
01814     }
01815 
01816     return( s );
01817 }
01818 
01819 
01820 /*
01821  * Print arbitrary stuff, for debugging.
01822  */
01823 
01824 #define BPLEN 48
01825 static void
01826 bprint( char *data, int len )
01827 {
01828     static char      hexdig[] = "0123456789abcdef";
01829     char      out[ BPLEN ];
01830     int              i = 0;
01831 
01832     memset( out, 0, BPLEN );
01833     for ( ;; ) {
01834        if ( len < 1 ) {
01835               fprintf( stderr, "\t%s\n", ( i == 0 ) ? "(end)" : out );
01836            break;
01837        }
01838 
01839 #ifndef HEX
01840        if ( isgraph( (unsigned char)*data )) {
01841            out[ i ] = ' ';
01842            out[ i+1 ] = *data;
01843        } else {
01844 #endif
01845            out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
01846            out[ i+1 ] = hexdig[ *data & 0x0f ];
01847 #ifndef HEX
01848        }
01849 #endif
01850        i += 2;
01851        len--;
01852        data++;
01853 
01854        if ( i > BPLEN - 2 ) {
01855            fprintf( stderr, "\t%s\n", out );
01856            memset( out, 0, BPLEN );
01857            i = 0;
01858            continue;
01859        }
01860        out[ i++ ] = ' ';
01861     }
01862 
01863     fflush( stderr );
01864 }