home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / libraries / libldap / test.c < prev    next >
C/C++ Source or Header  |  2001-07-22  |  22KB  |  883 lines

  1. /* $OpenLDAP: pkg/ldap/libraries/libldap/test.c,v 1.20.6.5 2001/07/21 19:01:40 kurt Exp $ */
  2. /*
  3.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  4.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  5.  */
  6.  
  7. #include "portable.h"
  8.  
  9. #include <stdio.h>
  10.  
  11. #include <ac/stdlib.h>
  12.  
  13. #include <ac/ctype.h>
  14. #include <ac/socket.h>
  15. #include <ac/string.h>
  16. #include <ac/time.h>
  17. #include <ac/unistd.h>
  18.  
  19. #include <sys/stat.h>
  20.  
  21. #ifdef HAVE_SYS_FILE_H
  22. #include <sys/file.h>
  23. #endif
  24. #ifdef HAVE_IO_H
  25. #include <io.h>
  26. #endif
  27.  
  28. #include <fcntl.h>
  29.  
  30. /* including the "internal" defs is legit and nec. since this test routine has 
  31.  * a-priori knowledge of libldap internal workings.
  32.  * hodges@stanford.edu 5-Feb-96
  33.  */
  34. #include "ldap-int.h"
  35.  
  36. /* local functions */
  37. #ifndef HAVE_GETLINE
  38. static char *getline LDAP_P(( char *line, int len, FILE *fp, char *prompt ));
  39. #endif
  40. static char **get_list LDAP_P(( char *prompt ));
  41. static int file_read LDAP_P(( char *path, struct berval *bv ));
  42. static LDAPMod **get_modlist LDAP_P(( char *prompt1, char *prompt2, char *prompt3 ));
  43. static void handle_result LDAP_P(( LDAP *ld, LDAPMessage *lm ));
  44. static void print_ldap_result LDAP_P(( LDAP *ld, LDAPMessage *lm, char *s ));
  45. static void print_search_entry LDAP_P(( LDAP *ld, LDAPMessage *res ));
  46. static void free_list LDAP_P(( char **list ));
  47.  
  48. #define NOCACHEERRMSG    "don't compile with -DLDAP_NOCACHE if you desire local caching"
  49.  
  50. static char *dnsuffix;
  51.  
  52. #ifndef HAVE_GETLINE
  53. static char *
  54. getline( char *line, int len, FILE *fp, char *prompt )
  55. {
  56.     printf(prompt);
  57.  
  58.     if ( fgets( line, len, fp ) == NULL )
  59.         return( NULL );
  60.  
  61.     line[ strlen( line ) - 1 ] = '\0';
  62.  
  63.     return( line );
  64. }
  65. #endif
  66.  
  67. static char **
  68. get_list( char *prompt )
  69. {
  70.     static char    buf[256];
  71.     int        num;
  72.     char        **result;
  73.  
  74.     num = 0;
  75.     result = (char **) 0;
  76.     while ( 1 ) {
  77.         getline( buf, sizeof(buf), stdin, prompt );
  78.  
  79.         if ( *buf == '\0' )
  80.             break;
  81.  
  82.         if ( result == (char **) 0 )
  83.             result = (char **) malloc( sizeof(char *) );
  84.         else
  85.             result = (char **) realloc( result,
  86.                 sizeof(char *) * (num + 1) );
  87.  
  88.         result[num++] = (char *) strdup( buf );
  89.     }
  90.     if ( result == (char **) 0 )
  91.         return( NULL );
  92.     result = (char **) realloc( result, sizeof(char *) * (num + 1) );
  93.     result[num] = NULL;
  94.  
  95.     return( result );
  96. }
  97.  
  98.  
  99. static void
  100. free_list( char **list )
  101. {
  102.     int    i;
  103.  
  104.     if ( list != NULL ) {
  105.         for ( i = 0; list[ i ] != NULL; ++i ) {
  106.             free( list[ i ] );
  107.         }
  108.         free( (char *)list );
  109.     }
  110. }
  111.  
  112.  
  113. static int
  114. file_read( char *path, struct berval *bv )
  115. {
  116.     FILE        *fp;
  117.     ber_slen_t    rlen;
  118.     int        eof;
  119.  
  120.     if (( fp = fopen( path, "r" )) == NULL ) {
  121.             perror( path );
  122.         return( -1 );
  123.     }
  124.  
  125.     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
  126.         perror( path );
  127.         fclose( fp );
  128.         return( -1 );
  129.     }
  130.  
  131.     bv->bv_len = ftell( fp );
  132.  
  133.     if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
  134.         perror( "malloc" );
  135.         fclose( fp );
  136.         return( -1 );
  137.     }
  138.  
  139.     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
  140.         perror( path );
  141.         fclose( fp );
  142.         return( -1 );
  143.     }
  144.  
  145.     rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
  146.     eof = feof( fp );
  147.     fclose( fp );
  148.  
  149.     if ( (ber_len_t) rlen != bv->bv_len ) {
  150.         perror( path );
  151.         free( bv->bv_val );
  152.         return( -1 );
  153.     }
  154.  
  155.     return( bv->bv_len );
  156. }
  157.  
  158.  
  159. static LDAPMod **
  160. get_modlist( char *prompt1, char *prompt2, char *prompt3 )
  161. {
  162.     static char    buf[256];
  163.     int        num;
  164.     LDAPMod        tmp;
  165.     LDAPMod        **result;
  166.     struct berval    **bvals;
  167.  
  168.     num = 0;
  169.     result = NULL;
  170.     while ( 1 ) {
  171.         if ( prompt1 ) {
  172.             getline( buf, sizeof(buf), stdin, prompt1 );
  173.             tmp.mod_op = atoi( buf );
  174.  
  175.             if ( tmp.mod_op == -1 || buf[0] == '\0' )
  176.                 break;
  177.         }
  178.  
  179.         getline( buf, sizeof(buf), stdin, prompt2 );
  180.         if ( buf[0] == '\0' )
  181.             break;
  182.         tmp.mod_type = strdup( buf );
  183.  
  184.         tmp.mod_values = get_list( prompt3 );
  185.  
  186.         if ( tmp.mod_values != NULL ) {
  187.             int    i;
  188.  
  189.             for ( i = 0; tmp.mod_values[i] != NULL; ++i )
  190.                 ;
  191.             bvals = (struct berval **)calloc( i + 1,
  192.                 sizeof( struct berval *));
  193.             for ( i = 0; tmp.mod_values[i] != NULL; ++i ) {
  194.                 bvals[i] = (struct berval *)malloc(
  195.                     sizeof( struct berval ));
  196.                 if ( strncmp( tmp.mod_values[i], "{FILE}",
  197.                     6 ) == 0 ) {
  198.                     if ( file_read( tmp.mod_values[i] + 6,
  199.                         bvals[i] ) < 0 ) {
  200.                         return( NULL );
  201.                     }
  202.                 } else {
  203.                     bvals[i]->bv_val = tmp.mod_values[i];
  204.                     bvals[i]->bv_len =
  205.                         strlen( tmp.mod_values[i] );
  206.                 }
  207.             }
  208.             tmp.mod_bvalues = bvals;
  209.             tmp.mod_op |= LDAP_MOD_BVALUES;
  210.         }
  211.  
  212.         if ( result == NULL )
  213.             result = (LDAPMod **) malloc( sizeof(LDAPMod *) );
  214.         else
  215.             result = (LDAPMod **) realloc( result,
  216.                 sizeof(LDAPMod *) * (num + 1) );
  217.  
  218.         result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) );
  219.         *(result[num]) = tmp;    /* struct copy */
  220.         num++;
  221.     }
  222.     if ( result == NULL )
  223.         return( NULL );
  224.     result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) );
  225.     result[num] = NULL;
  226.  
  227.     return( result );
  228. }
  229.  
  230.  
  231. static int
  232. bind_prompt( LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
  233. {
  234.     static char    dn[256], passwd[256];
  235.     int    authmethod;
  236.  
  237.     printf("rebind for request=%d msgid=%ld url=%s\n",
  238.         request, (long) msgid, url );
  239.  
  240. #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
  241.         getline( dn, sizeof(dn), stdin,
  242.             "re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " );
  243.     if (( authmethod = atoi( dn )) == 3 ) {
  244.         authmethod = LDAP_AUTH_KRBV4;
  245.         } else {
  246.         authmethod |= 0x80;
  247.         }
  248. #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  249.     authmethod = LDAP_AUTH_SIMPLE;
  250. #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  251.  
  252.         getline( dn, sizeof(dn), stdin, "re-bind dn? " );
  253.         strcat( dn, dnsuffix );
  254.  
  255.     if ( authmethod == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
  256.             getline( passwd, sizeof(passwd), stdin,
  257.                 "re-bind password? " );
  258.         } else {
  259.             passwd[0] = '\0';
  260.         }
  261.  
  262.     return ldap_bind_s( ld, dn, passwd, authmethod);
  263. }
  264.  
  265.  
  266. int
  267. main( int argc, char **argv )
  268. {
  269.     LDAP        *ld = NULL;
  270.     int        i, c, port, errflg, method, id, msgtype;
  271.     char        line[256], command1, command2, command3;
  272.     char        passwd[64], dn[256], rdn[64], attr[64], value[256];
  273.     char        filter[256], *host, **types;
  274.     char        **exdn;
  275.     char        *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
  276.     int        bound, all, scope, attrsonly;
  277.     LDAPMessage    *res;
  278.     LDAPMod        **mods, **attrs;
  279.     struct timeval    timeout;
  280.     char        *copyfname = NULL;
  281.     int        copyoptions = 0;
  282.     LDAPURLDesc    *ludp;
  283.  
  284.     host = NULL;
  285.     port = LDAP_PORT;
  286.     dnsuffix = "";
  287.     errflg = 0;
  288.  
  289.     while (( c = getopt( argc, argv, "h:d:s:p:t:T:" )) != -1 ) {
  290.         switch( c ) {
  291.         case 'd':
  292. #ifdef LDAP_DEBUG
  293.             ldap_debug = atoi( optarg );
  294. #ifdef LBER_DEBUG
  295.             if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
  296.                 ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
  297.             }
  298. #endif
  299. #else
  300.             printf( "Compile with -DLDAP_DEBUG for debugging\n" );
  301. #endif
  302.             break;
  303.  
  304.         case 'h':
  305.             host = optarg;
  306.             break;
  307.  
  308.         case 's':
  309.             dnsuffix = optarg;
  310.             break;
  311.  
  312.         case 'p':
  313.             port = atoi( optarg );
  314.             break;
  315.  
  316.         case 't':    /* copy ber's to given file */
  317.             copyfname = strdup( optarg );
  318. /*            copyoptions = LBER_TO_FILE; */
  319.             break;
  320.  
  321.         case 'T':    /* only output ber's to given file */
  322.             copyfname = strdup( optarg );
  323. /*            copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */
  324.             break;
  325.  
  326.         default:
  327.             ++errflg;
  328.         }
  329.     }
  330.  
  331.     if ( host == NULL && optind == argc - 1 ) {
  332.         host = argv[ optind ];
  333.         ++optind;
  334.     }
  335.  
  336.     if ( errflg || optind < argc - 1 ) {
  337.         fprintf( stderr, usage, argv[ 0 ] );
  338.         exit( EXIT_FAILURE );
  339.     }
  340.     
  341.     printf( "ldap_init( %s, %d )\n",
  342.         host == NULL ? "(null)" : host, port );
  343.  
  344.     ld = ldap_init( host, port );
  345.  
  346.     if ( ld == NULL ) {
  347.         perror( "ldap_init" );
  348.         exit( EXIT_FAILURE );
  349.     }
  350.  
  351.     if ( copyfname != NULL ) {
  352.         if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY | O_CREAT,
  353.             0600 ))  == -1 ) {
  354.             perror( copyfname );
  355.             exit ( EXIT_FAILURE );
  356.         }
  357.         ld->ld_sb->sb_options = copyoptions;
  358.     }
  359.  
  360.     bound = 0;
  361.     timeout.tv_sec = 0;
  362.     timeout.tv_usec = 0;
  363.  
  364.     (void) memset( line, '\0', sizeof(line) );
  365.     while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) {
  366.         command1 = line[0];
  367.         command2 = line[1];
  368.         command3 = line[2];
  369.  
  370.         switch ( command1 ) {
  371.         case 'a':    /* add or abandon */
  372.             switch ( command2 ) {
  373.             case 'd':    /* add */
  374.                 getline( dn, sizeof(dn), stdin, "dn? " );
  375.                 strcat( dn, dnsuffix );
  376.                 if ( (attrs = get_modlist( NULL, "attr? ",
  377.                     "value? " )) == NULL )
  378.                     break;
  379.                 if ( (id = ldap_add( ld, dn, attrs )) == -1 )
  380.                     ldap_perror( ld, "ldap_add" );
  381.                 else
  382.                     printf( "Add initiated with id %d\n",
  383.                         id );
  384.                 break;
  385.  
  386.             case 'b':    /* abandon */
  387.                 getline( line, sizeof(line), stdin, "msgid? " );
  388.                 id = atoi( line );
  389.                 if ( ldap_abandon( ld, id ) != 0 )
  390.                     ldap_perror( ld, "ldap_abandon" );
  391.                 else
  392.                     printf( "Abandon successful\n" );
  393.                 break;
  394.             default:
  395.                 printf( "Possibilities: [ad]d, [ab]ort\n" );
  396.             }
  397.             break;
  398.  
  399.         case 'b':    /* asynch bind */
  400. #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
  401.             getline( line, sizeof(line), stdin,
  402.                 "method (0->simple, 1->krbv41, 2->krbv42)? " );
  403.             method = atoi( line ) | 0x80;
  404. #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  405.             method = LDAP_AUTH_SIMPLE;
  406. #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  407.             getline( dn, sizeof(dn), stdin, "dn? " );
  408.             strcat( dn, dnsuffix );
  409.  
  410.             if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' )
  411.                 getline( passwd, sizeof(passwd), stdin,
  412.                     "password? " );
  413.             else
  414.                 passwd[0] = '\0';
  415.  
  416.             if ( ldap_bind( ld, dn, passwd, method ) == -1 ) {
  417.                 fprintf( stderr, "ldap_bind failed\n" );
  418.                 ldap_perror( ld, "ldap_bind" );
  419.             } else {
  420.                 printf( "Bind initiated\n" );
  421.                 bound = 1;
  422.             }
  423.             break;
  424.  
  425.         case 'B':    /* synch bind */
  426. #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
  427.             getline( line, sizeof(line), stdin,
  428.                 "method 0->simple 1->krbv41 2->krbv42 3->krb? " );
  429.             method = atoi( line );
  430.             if ( method == 3 )
  431.                 method = LDAP_AUTH_KRBV4;
  432.             else
  433.                 method = method | 0x80;
  434. #else /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  435.             method = LDAP_AUTH_SIMPLE;
  436. #endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND */
  437.             getline( dn, sizeof(dn), stdin, "dn? " );
  438.             strcat( dn, dnsuffix );
  439.  
  440.             if ( dn[0] != '\0' )
  441.                 getline( passwd, sizeof(passwd), stdin,
  442.                     "password? " );
  443.             else
  444.                 passwd[0] = '\0';
  445.  
  446.             if ( ldap_bind_s( ld, dn, passwd, method ) !=
  447.                 LDAP_SUCCESS ) {
  448.                 fprintf( stderr, "ldap_bind_s failed\n" );
  449.                 ldap_perror( ld, "ldap_bind_s" );
  450.             } else {
  451.                 printf( "Bind successful\n" );
  452.                 bound = 1;
  453.             }
  454.             break;
  455.  
  456.         case 'c':    /* compare */
  457.             getline( dn, sizeof(dn), stdin, "dn? " );
  458.             strcat( dn, dnsuffix );
  459.             getline( attr, sizeof(attr), stdin, "attr? " );
  460.             getline( value, sizeof(value), stdin, "value? " );
  461.  
  462.             if ( (id = ldap_compare( ld, dn, attr, value )) == -1 )
  463.                 ldap_perror( ld, "ldap_compare" );
  464.             else
  465.                 printf( "Compare initiated with id %d\n", id );
  466.             break;
  467.  
  468.         case 'd':    /* turn on debugging */
  469. #ifdef LDAP_DEBUG
  470.             getline( line, sizeof(line), stdin, "debug level? " );
  471.             ldap_debug = atoi( line );
  472. #ifdef LBER_DEBUG
  473.             if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
  474.                 ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
  475.             }
  476. #endif
  477. #else
  478.             printf( "Compile with -DLDAP_DEBUG for debugging\n" );
  479. #endif
  480.             break;
  481.  
  482.         case 'E':    /* explode a dn */
  483.             getline( line, sizeof(line), stdin, "dn? " );
  484.             exdn = ldap_explode_dn( line, 0 );
  485.             for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) {
  486.                 printf( "\t%s\n", exdn[i] );
  487.             }
  488.             break;
  489.  
  490.         case 'g':    /* set next msgid */
  491.             getline( line, sizeof(line), stdin, "msgid? " );
  492.             ld->ld_msgid = atoi( line );
  493.             break;
  494.  
  495.         case 'v':    /* set version number */
  496.             getline( line, sizeof(line), stdin, "version? " );
  497.             ld->ld_version = atoi( line );
  498.             break;
  499.  
  500.         case 'm':    /* modify or modifyrdn */
  501.             if ( strncmp( line, "modify", 4 ) == 0 ) {
  502.                 getline( dn, sizeof(dn), stdin, "dn? " );
  503.                 strcat( dn, dnsuffix );
  504.                 if ( (mods = get_modlist(
  505.                     "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ",
  506.                     "attribute type? ", "attribute value? " ))
  507.                     == NULL )
  508.                     break;
  509.                 if ( (id = ldap_modify( ld, dn, mods )) == -1 )
  510.                     ldap_perror( ld, "ldap_modify" );
  511.                 else
  512.                     printf( "Modify initiated with id %d\n",
  513.                         id );
  514.             } else if ( strncmp( line, "modrdn", 4 ) == 0 ) {
  515.                 getline( dn, sizeof(dn), stdin, "dn? " );
  516.                 strcat( dn, dnsuffix );
  517.                 getline( rdn, sizeof(rdn), stdin, "newrdn? " );
  518.                 if ( (id = ldap_modrdn( ld, dn, rdn )) == -1 )
  519.                     ldap_perror( ld, "ldap_modrdn" );
  520.                 else
  521.                     printf( "Modrdn initiated with id %d\n",
  522.                         id );
  523.             } else {
  524.                 printf( "Possibilities: [modi]fy, [modr]dn\n" );
  525.             }
  526.             break;
  527.  
  528.         case 'q':    /* quit */
  529.             ldap_unbind( ld );
  530.             exit( EXIT_SUCCESS );
  531.             break;
  532.  
  533.         case 'r':    /* result or remove */
  534.             switch ( command3 ) {
  535.             case 's':    /* result */
  536.                 getline( line, sizeof(line), stdin,
  537.                     "msgid (-1=>any)? " );
  538.                 if ( line[0] == '\0' )
  539.                     id = -1;
  540.                 else
  541.                     id = atoi( line );
  542.                 getline( line, sizeof(line), stdin,
  543.                     "all (0=>any, 1=>all)? " );
  544.                 if ( line[0] == '\0' )
  545.                     all = 1;
  546.                 else
  547.                     all = atoi( line );
  548.                 if (( msgtype = ldap_result( ld, id, all,
  549.                     &timeout, &res )) < 1 ) {
  550.                     ldap_perror( ld, "ldap_result" );
  551.                     break;
  552.                 }
  553.                 printf( "\nresult: msgtype %d msgid %d\n",
  554.                     msgtype, res->lm_msgid );
  555.                 handle_result( ld, res );
  556.                 res = NULL;
  557.                 break;
  558.  
  559.             case 'm':    /* remove */
  560.                 getline( dn, sizeof(dn), stdin, "dn? " );
  561.                 strcat( dn, dnsuffix );
  562.                 if ( (id = ldap_delete( ld, dn )) == -1 )
  563.                     ldap_perror( ld, "ldap_delete" );
  564.                 else
  565.                     printf( "Remove initiated with id %d\n",
  566.                         id );
  567.                 break;
  568.  
  569.             default:
  570.                 printf( "Possibilities: [rem]ove, [res]ult\n" );
  571.                 break;
  572.             }
  573.             break;
  574.  
  575.         case 's':    /* search */
  576.             getline( dn, sizeof(dn), stdin, "searchbase? " );
  577.             strcat( dn, dnsuffix );
  578.             getline( line, sizeof(line), stdin,
  579.                 "scope (0=Base, 1=One Level, 2=Subtree)? " );
  580.             scope = atoi( line );
  581.             getline( filter, sizeof(filter), stdin,
  582.                 "search filter (e.g. sn=jones)? " );
  583.             types = get_list( "attrs to return? " );
  584.             getline( line, sizeof(line), stdin,
  585.                 "attrsonly (0=attrs&values, 1=attrs only)? " );
  586.             attrsonly = atoi( line );
  587.  
  588.                 if (( id = ldap_search( ld, dn, scope, filter,
  589.                     types, attrsonly  )) == -1 ) {
  590.                 ldap_perror( ld, "ldap_search" );
  591.                 } else {
  592.                 printf( "Search initiated with id %d\n", id );
  593.                 }
  594.             free_list( types );
  595.             break;
  596.  
  597.         case 't':    /* set timeout value */
  598.             getline( line, sizeof(line), stdin, "timeout? " );
  599.             timeout.tv_sec = atoi( line );
  600.             break;
  601.  
  602.         case 'l':    /* URL search */
  603.             getline( line, sizeof(line), stdin,
  604.                 "attrsonly (0=attrs&values, 1=attrs only)? " );
  605.             attrsonly = atoi( line );
  606.             getline( line, sizeof(line), stdin, "LDAP URL? " );
  607.             if (( id = ldap_url_search( ld, line, attrsonly  ))
  608.                 == -1 ) {
  609.                 ldap_perror( ld, "ldap_url_search" );
  610.             } else {
  611.                 printf( "URL search initiated with id %d\n", id );
  612.             }
  613.             break;
  614.  
  615.         case 'p':    /* parse LDAP URL */
  616.             getline( line, sizeof(line), stdin, "LDAP URL? " );
  617.             if (( i = ldap_url_parse( line, &ludp )) != 0 ) {
  618.                 fprintf( stderr, "ldap_url_parse: error %d\n", i );
  619.             } else {
  620.                 printf( "\t  host: " );
  621.                 if ( ludp->lud_host == NULL ) {
  622.                 printf( "DEFAULT\n" );
  623.                 } else {
  624.                 printf( "<%s>\n", ludp->lud_host );
  625.                 }
  626.                 printf( "\t  port: " );
  627.                 if ( ludp->lud_port == 0 ) {
  628.                 printf( "DEFAULT\n" );
  629.                 } else {
  630.                 printf( "%d\n", ludp->lud_port );
  631.                 }
  632.                 printf( "\t    dn: <%s>\n", ludp->lud_dn );
  633.                 printf( "\t attrs:" );
  634.                 if ( ludp->lud_attrs == NULL ) {
  635.                 printf( " ALL" );
  636.                 } else {
  637.                 for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) {
  638.                     printf( " <%s>", ludp->lud_attrs[ i ] );
  639.                 }
  640.                 }
  641.                 printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_ONELEVEL ?
  642.                 "ONE" : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" :
  643.                 ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" : "**invalid**" );
  644.                 printf( "\tfilter: <%s>\n", ludp->lud_filter );
  645.                 ldap_free_urldesc( ludp );
  646.             }
  647.                 break;
  648.  
  649.         case 'n':    /* set dn suffix, for convenience */
  650.             getline( line, sizeof(line), stdin, "DN suffix? " );
  651.             strcpy( dnsuffix, line );
  652.             break;
  653.  
  654.         case 'e':    /* enable cache */
  655. #ifdef LDAP_NOCACHE
  656.             printf( NOCACHEERRMSG );
  657. #else /* LDAP_NOCACHE */
  658.             getline( line, sizeof(line), stdin, "Cache timeout (secs)? " );
  659.             i = atoi( line );
  660.             getline( line, sizeof(line), stdin, "Maximum memory to use (bytes)? " );
  661.             if ( ldap_enable_cache( ld, i, atoi( line )) == 0 ) {
  662.                 printf( "local cache is on\n" ); 
  663.             } else {
  664.                 printf( "ldap_enable_cache failed\n" ); 
  665.             }
  666. #endif /* LDAP_NOCACHE */
  667.             break;
  668.  
  669.         case 'x':    /* uncache entry */
  670. #ifdef LDAP_NOCACHE
  671.             printf( NOCACHEERRMSG );
  672. #else /* LDAP_NOCACHE */
  673.             getline( line, sizeof(line), stdin, "DN? " );
  674.             ldap_uncache_entry( ld, line );
  675. #endif /* LDAP_NOCACHE */
  676.             break;
  677.  
  678.         case 'X':    /* uncache request */
  679. #ifdef LDAP_NOCACHE
  680.             printf( NOCACHEERRMSG );
  681. #else /* LDAP_NOCACHE */
  682.             getline( line, sizeof(line), stdin, "request msgid? " );
  683.             ldap_uncache_request( ld, atoi( line ));
  684. #endif /* LDAP_NOCACHE */
  685.             break;
  686.  
  687.         case 'o':    /* set ldap options */
  688.             getline( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" );
  689.             ld->ld_deref = atoi( line );
  690.             getline( line, sizeof(line), stdin, "timelimit?" );
  691.             ld->ld_timelimit = atoi( line );
  692.             getline( line, sizeof(line), stdin, "sizelimit?" );
  693.             ld->ld_sizelimit = atoi( line );
  694.  
  695.             LDAP_BOOL_ZERO(&ld->ld_options);
  696.  
  697.             getline( line, sizeof(line), stdin,
  698.                 "Recognize and chase referrals (0=no, 1=yes)?" );
  699.             if ( atoi( line ) != 0 ) {
  700.                 LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_REFERRALS);
  701.                 getline( line, sizeof(line), stdin,
  702.                     "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" );
  703.                 if ( atoi( line ) != 0 ) {
  704.                     ldap_set_rebind_proc( ld, bind_prompt );
  705.                 }
  706.             }
  707.             break;
  708.  
  709.         case 'O':    /* set cache options */
  710. #ifdef LDAP_NOCACHE
  711.             printf( NOCACHEERRMSG );
  712. #else /* LDAP_NOCACHE */
  713.             getline( line, sizeof(line), stdin, "cache errors (0=smart, 1=never, 2=always)?" );
  714.             switch( atoi( line )) {
  715.             case 0:
  716.                 ldap_set_cache_options( ld, 0 );
  717.                 break;
  718.             case 1:
  719.                 ldap_set_cache_options( ld,
  720.                     LDAP_CACHE_OPT_CACHENOERRS );
  721.                 break;
  722.             case 2:
  723.                 ldap_set_cache_options( ld,
  724.                     LDAP_CACHE_OPT_CACHEALLERRS );
  725.                 break;
  726.             default:
  727.                 printf( "not a valid cache option\n" );
  728.             }
  729. #endif /* LDAP_NOCACHE */
  730.             break;
  731.  
  732.         case '?':    /* help */
  733.     printf( "Commands: [ad]d         [ab]andon         [b]ind\n" );
  734.     printf( "          [B]ind async  [c]ompare         [l]URL search\n" );
  735.     printf( "          [modi]fy      [modr]dn          [rem]ove\n" );
  736.     printf( "          [res]ult      [s]earch          [q]uit/unbind\n\n" );
  737.     printf( "          [u]fn search  [ut]fn search with timeout\n" );
  738.     printf( "          [d]ebug       [e]nable cache    set ms[g]id\n" );
  739.     printf( "          d[n]suffix    [t]imeout         [v]ersion\n" );
  740.     printf( "          [U]fn prefix  [x]uncache entry  [X]uncache request\n" );
  741.     printf( "          [?]help       [o]ptions         [O]cache options\n" );
  742.     printf( "          [E]xplode dn  [p]arse LDAP URL\n" );
  743.             break;
  744.  
  745.         default:
  746.             printf( "Invalid command.  Type ? for help.\n" );
  747.             break;
  748.         }
  749.  
  750.         (void) memset( line, '\0', sizeof(line) );
  751.     }
  752.  
  753.     return( 0 );
  754. }
  755.  
  756. static void
  757. handle_result( LDAP *ld, LDAPMessage *lm )
  758. {
  759.     switch ( lm->lm_msgtype ) {
  760.     case LDAP_RES_COMPARE:
  761.         printf( "Compare result\n" );
  762.         print_ldap_result( ld, lm, "compare" );
  763.         break;
  764.  
  765.     case LDAP_RES_SEARCH_RESULT:
  766.         printf( "Search result\n" );
  767.         print_ldap_result( ld, lm, "search" );
  768.         break;
  769.  
  770.     case LDAP_RES_SEARCH_ENTRY:
  771.         printf( "Search entry\n" );
  772.         print_search_entry( ld, lm );
  773.         break;
  774.  
  775.     case LDAP_RES_ADD:
  776.         printf( "Add result\n" );
  777.         print_ldap_result( ld, lm, "add" );
  778.         break;
  779.  
  780.     case LDAP_RES_DELETE:
  781.         printf( "Delete result\n" );
  782.         print_ldap_result( ld, lm, "delete" );
  783.         break;
  784.  
  785.     case LDAP_RES_MODRDN:
  786.         printf( "ModRDN result\n" );
  787.         print_ldap_result( ld, lm, "modrdn" );
  788.         break;
  789.  
  790.     case LDAP_RES_BIND:
  791.         printf( "Bind result\n" );
  792.         print_ldap_result( ld, lm, "bind" );
  793.         break;
  794.  
  795.     default:
  796.         printf( "Unknown result type 0x%lx\n",
  797.                 (unsigned long) lm->lm_msgtype );
  798.         print_ldap_result( ld, lm, "unknown" );
  799.     }
  800. }
  801.  
  802. static void
  803. print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s )
  804. {
  805.     ldap_result2error( ld, lm, 1 );
  806.     ldap_perror( ld, s );
  807. /*
  808.     if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
  809.         fprintf( stderr, "Additional info: %s\n", ld->ld_error );
  810.     if ( LDAP_NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
  811.         fprintf( stderr, "Matched DN: %s\n", ld->ld_matched );
  812. */
  813. }
  814.  
  815. static void
  816. print_search_entry( LDAP *ld, LDAPMessage *res )
  817. {
  818.     LDAPMessage    *e;
  819.  
  820.     for ( e = ldap_first_entry( ld, res ); e != NULL;
  821.         e = ldap_next_entry( ld, e ) )
  822.     {
  823.         BerElement    *ber = NULL;
  824.         char *a, *dn, *ufn;
  825.  
  826.         if ( e->lm_msgtype == LDAP_RES_SEARCH_RESULT )
  827.             break;
  828.  
  829.         dn = ldap_get_dn( ld, e );
  830.         printf( "\tDN: %s\n", dn );
  831.  
  832.         ufn = ldap_dn2ufn( dn );
  833.         printf( "\tUFN: %s\n", ufn );
  834.  
  835.         free( dn );
  836.         free( ufn );
  837.  
  838.         for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
  839.             a = ldap_next_attribute( ld, e, ber ) )
  840.         {
  841.             struct berval    **vals;
  842.  
  843.             printf( "\t\tATTR: %s\n", a );
  844.             if ( (vals = ldap_get_values_len( ld, e, a ))
  845.                 == NULL ) {
  846.                 printf( "\t\t\t(no values)\n" );
  847.             } else {
  848.                 int i;
  849.                 for ( i = 0; vals[i] != NULL; i++ ) {
  850.                     int    j, nonascii;
  851.  
  852.                     nonascii = 0;
  853.                     for ( j = 0; (ber_len_t) j < vals[i]->bv_len; j++ )
  854.                         if ( !isascii( vals[i]->bv_val[j] ) ) {
  855.                             nonascii = 1;
  856.                             break;
  857.                         }
  858.  
  859.                     if ( nonascii ) {
  860.                         printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len );
  861. #ifdef BPRINT_NONASCII
  862.                         ber_bprint( vals[i]->bv_val,
  863.                             vals[i]->bv_len );
  864. #endif /* BPRINT_NONASCII */
  865.                         continue;
  866.                     }
  867.                     printf( "\t\t\tlength (%ld) %s\n",
  868.                         vals[i]->bv_len, vals[i]->bv_val );
  869.                 }
  870.                 ber_bvecfree( vals );
  871.             }
  872.         }
  873.  
  874.         if(ber != NULL) {
  875.             ber_free( ber, 0 );
  876.         }
  877.     }
  878.  
  879.     if ( res->lm_msgtype == LDAP_RES_SEARCH_RESULT
  880.         || res->lm_chain != NULL )
  881.         print_ldap_result( ld, res, "search" );
  882. }
  883.