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