]> git.sur5r.net Git - openldap/blob - clients/tools/ldapdelete.c
initialize Sockbuf * to NULL
[openldap] / clients / tools / ldapdelete.c
1 /* ldapdelete.c - simple program to delete an entry using LDAP */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/stdlib.h>
13 #include <ac/ctype.h>
14
15 #include <ac/signal.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
18
19 #include <ldap.h>
20 #include "lutil_ldap.h"
21 #include "ldap_defaults.h"
22
23 static char     *prog;
24 static char     *binddn = NULL;
25 static struct berval passwd = { 0, NULL };
26 static char *ldapuri = NULL;
27 static char     *ldaphost = NULL;
28 static int      ldapport = 0;
29 static int      prune = 0;
30 #ifdef HAVE_CYRUS_SASL
31 static unsigned sasl_flags = LDAP_SASL_AUTOMATIC;
32 static char     *sasl_mech = NULL;
33 static char *sasl_realm = NULL;
34 static char     *sasl_authc_id = NULL;
35 static char     *sasl_authz_id = NULL;
36 static char     *sasl_secprops = NULL;
37 #endif
38 static int      use_tls = 0;
39 static int      not, verbose, contoper;
40 static LDAP     *ld = NULL;
41
42 static int dodelete LDAP_P((
43     LDAP *ld,
44     const char *dn));
45
46 static int deletechildren LDAP_P((
47         LDAP *ld,
48         const char *dn ));
49
50 static void
51 usage( const char *s )
52 {
53         fprintf( stderr,
54 "Delete entries from an LDAP server\n\n"
55 "usage: %s [options] [dn]...\n"
56 "       dn: list of DNs to delete. If not given, it will be readed from stdin\n"
57 "           or from the file specified with \"-f file\".\n"
58 "Delete Options:\n"
59 "  -r         delete recursively\n"
60
61 "Common options:\n"
62 "  -d level   set LDAP debugging level to `level'\n"
63 "  -D binddn  bind DN\n"
64 "  -f file    read operations from `file'\n"
65 "  -h host    LDAP server\n"
66 "  -H URI     LDAP Uniform Resource Indentifier(s)\n"
67 "  -I         use SASL Interactive mode\n"
68 "  -k         use Kerberos authentication\n"
69 "  -K         like -k, but do only step 1 of the Kerberos bind\n"
70 "  -M         enable Manage DSA IT control (-MM to make critical)\n"
71 "  -n         show what would be done but don't actually search\n"
72 "  -O props   SASL security properties\n"
73 "  -p port    port on LDAP server\n"
74 "  -P version procotol version (default: 3)\n"
75 "  -Q         use SASL Quiet mode\n"
76 "  -R realm   SASL realm\n"
77 "  -U user    SASL authentication identity (username)\n"
78 "  -v         run in verbose mode (diagnostics to standard output)\n"
79 "  -w passwd  bind passwd (for simple authentication)\n"
80 "  -W         prompt for bind passwd\n"
81 "  -x         Simple authentication\n"
82 "  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
83 "  -Y mech    SASL mechanism\n"
84 "  -Z         Start TLS request (-ZZ to require successful response)\n"
85 ,               s );
86
87         exit( EXIT_FAILURE );
88 }
89
90
91 int
92 main( int argc, char **argv )
93 {
94         char            buf[ 4096 ];
95         FILE            *fp;
96         int             i, rc, authmethod, referrals, want_bindpw, version, debug, manageDSAit;
97
98     not = verbose = contoper = want_bindpw = debug = manageDSAit = referrals = 0;
99     fp = NULL;
100     authmethod = -1;
101         version = -1;
102
103     prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : prog + 1;
104
105     while (( i = getopt( argc, argv, "cf:r"
106                 "Cd:D:h:H:IkKMnO:p:P:QR:U:vw:WxX:Y:Z" )) != EOF )
107         {
108         switch( i ) {
109         /* Delete Specific Options */
110         case 'c':       /* continuous operation mode */
111             ++contoper;
112             break;
113         case 'f':       /* read DNs from a file */
114                 if( fp != NULL ) {
115                         fprintf( stderr, "%s: -f previously specified\n", prog );
116                         return EXIT_FAILURE;
117                 }
118             if (( fp = fopen( optarg, "r" )) == NULL ) {
119                 perror( optarg );
120                 exit( EXIT_FAILURE );
121             }
122             break;
123         case 'r':
124                 prune = 1;
125                 break;
126
127         /* Common Options */
128         case 'C':
129                 referrals++;
130                 break;
131         case 'd':
132             debug |= atoi( optarg );
133             break;
134         case 'D':       /* bind DN */
135                 if( binddn != NULL ) {
136                         fprintf( stderr, "%s: -D previously specified\n", prog );
137                         return EXIT_FAILURE;
138                 }
139             binddn = strdup( optarg );
140             break;
141         case 'h':       /* ldap host */
142                 if( ldapuri != NULL ) {
143                         fprintf( stderr, "%s: -h incompatible with -H\n", prog );
144                         return EXIT_FAILURE;
145                 }
146                 if( ldaphost != NULL ) {
147                         fprintf( stderr, "%s: -h previously specified\n", prog );
148                         return EXIT_FAILURE;
149                 }
150             ldaphost = strdup( optarg );
151             break;
152         case 'H':       /* ldap URI */
153                 if( ldaphost != NULL ) {
154                         fprintf( stderr, "%s: -H incompatible with -h\n", prog );
155                         return EXIT_FAILURE;
156                 }
157                 if( ldapport ) {
158                         fprintf( stderr, "%s: -H incompatible with -p\n", prog );
159                         return EXIT_FAILURE;
160                 }
161                 if( ldapuri != NULL ) {
162                         fprintf( stderr, "%s: -H previously specified\n", prog );
163                         return EXIT_FAILURE;
164                 }
165             ldapuri = strdup( optarg );
166             break;
167         case 'I':
168 #ifdef HAVE_CYRUS_SASL
169                 if( version == LDAP_VERSION2 ) {
170                         fprintf( stderr, "%s: -I incompatible with version %d\n",
171                                 prog, version );
172                         return EXIT_FAILURE;
173                 }
174                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
175                         fprintf( stderr, "%s: incompatible previous "
176                                 "authentication choice\n",
177                                 prog );
178                         return EXIT_FAILURE;
179                 }
180                 authmethod = LDAP_AUTH_SASL;
181                 version = LDAP_VERSION3;
182                 sasl_flags = LDAP_SASL_INTERACTIVE;
183                 break;
184 #else
185                 fprintf( stderr, "%s: was not compiled with SASL support\n",
186                         prog );
187                 return( EXIT_FAILURE );
188 #endif
189         case 'k':       /* kerberos bind */
190 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
191                 if( version > LDAP_VERSION2 ) {
192                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
193                                 prog, version );
194                         return EXIT_FAILURE;
195                 }
196
197                 if( authmethod != -1 ) {
198                         fprintf( stderr, "%s: -k incompatible with previous "
199                                 "authentication choice\n", prog );
200                         return EXIT_FAILURE;
201                 }
202                         
203                 authmethod = LDAP_AUTH_KRBV4;
204 #else
205                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
206                 return EXIT_FAILURE;
207 #endif
208             break;
209         case 'K':       /* kerberos bind, part one only */
210 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
211                 if( version > LDAP_VERSION2 ) {
212                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
213                                 prog, version );
214                         return EXIT_FAILURE;
215                 }
216                 if( authmethod != -1 ) {
217                         fprintf( stderr, "%s: incompatible with previous "
218                                 "authentication choice\n", prog );
219                         return EXIT_FAILURE;
220                 }
221
222                 authmethod = LDAP_AUTH_KRBV41;
223 #else
224                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
225                 return( EXIT_FAILURE );
226 #endif
227             break;
228         case 'M':
229                 /* enable Manage DSA IT */
230                 if( version == LDAP_VERSION2 ) {
231                         fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
232                                 prog, version );
233                         return EXIT_FAILURE;
234                 }
235                 manageDSAit++;
236                 version = LDAP_VERSION3;
237                 break;
238         case 'n':       /* print deletes, don't actually do them */
239             ++not;
240             break;
241         case 'O':
242 #ifdef HAVE_CYRUS_SASL
243                 if( sasl_secprops != NULL ) {
244                         fprintf( stderr, "%s: -O previously specified\n", prog );
245                         return EXIT_FAILURE;
246                 }
247                 if( version == LDAP_VERSION2 ) {
248                         fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
249                                 prog, version );
250                         return EXIT_FAILURE;
251                 }
252                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
253                         fprintf( stderr, "%s: incompatible previous "
254                                 "authentication choice\n", prog );
255                         return EXIT_FAILURE;
256                 }
257                 authmethod = LDAP_AUTH_SASL;
258                 version = LDAP_VERSION3;
259                 sasl_secprops = strdup( optarg );
260 #else
261                 fprintf( stderr, "%s: not compiled with SASL support\n",
262                         prog );
263                 return( EXIT_FAILURE );
264 #endif
265                 break;
266         case 'p':
267                 if( ldapport ) {
268                         fprintf( stderr, "%s: -p previously specified\n", prog );
269                         return EXIT_FAILURE;
270                 }
271             ldapport = atoi( optarg );
272             break;
273         case 'P':
274                 switch( atoi(optarg) ) {
275                 case 2:
276                         if( version == LDAP_VERSION3 ) {
277                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
278                                         prog, version );
279                                 return EXIT_FAILURE;
280                         }
281                         version = LDAP_VERSION2;
282                         break;
283                 case 3:
284                         if( version == LDAP_VERSION2 ) {
285                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
286                                         prog, version );
287                                 return EXIT_FAILURE;
288                         }
289                         version = LDAP_VERSION3;
290                         break;
291                 default:
292                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
293                                 prog );
294                         usage( prog );
295                         return( EXIT_FAILURE );
296                 } break;
297         case 'Q':
298 #ifdef HAVE_CYRUS_SASL
299                 if( version == LDAP_VERSION2 ) {
300                         fprintf( stderr, "%s: -Q incompatible with version %d\n",
301                                 prog, version );
302                         return EXIT_FAILURE;
303                 }
304                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
305                         fprintf( stderr, "%s: incompatible previous "
306                                 "authentication choice\n",
307                                 prog );
308                         return EXIT_FAILURE;
309                 }
310                 authmethod = LDAP_AUTH_SASL;
311                 version = LDAP_VERSION3;
312                 sasl_flags = LDAP_SASL_QUIET;
313                 break;
314 #else
315                 fprintf( stderr, "%s: not compiled with SASL support\n",
316                         prog );
317                 return( EXIT_FAILURE );
318 #endif
319         case 'R':
320 #ifdef HAVE_CYRUS_SASL
321                 if( sasl_realm != NULL ) {
322                         fprintf( stderr, "%s: -R previously specified\n", prog );
323                         return EXIT_FAILURE;
324                 }
325                 if( version == LDAP_VERSION2 ) {
326                         fprintf( stderr, "%s: -R incompatible with version %d\n",
327                                 prog, version );
328                         return EXIT_FAILURE;
329                 }
330                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
331                         fprintf( stderr, "%s: incompatible previous "
332                                 "authentication choice\n",
333                                 prog );
334                         return EXIT_FAILURE;
335                 }
336                 authmethod = LDAP_AUTH_SASL;
337                 version = LDAP_VERSION3;
338                 sasl_realm = strdup( optarg );
339 #else
340                 fprintf( stderr, "%s: not compiled with SASL support\n",
341                         prog );
342                 return( EXIT_FAILURE );
343 #endif
344                 break;
345         case 'U':
346 #ifdef HAVE_CYRUS_SASL
347                 if( sasl_authc_id != NULL ) {
348                         fprintf( stderr, "%s: -U previously specified\n", prog );
349                         return EXIT_FAILURE;
350                 }
351                 if( version == LDAP_VERSION2 ) {
352                         fprintf( stderr, "%s: -U incompatible with version %d\n",
353                                 prog, version );
354                         return EXIT_FAILURE;
355                 }
356                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
357                         fprintf( stderr, "%s: incompatible previous "
358                                 "authentication choice\n",
359                                 prog );
360                         return EXIT_FAILURE;
361                 }
362                 authmethod = LDAP_AUTH_SASL;
363                 version = LDAP_VERSION3;
364                 sasl_authc_id = strdup( optarg );
365 #else
366                 fprintf( stderr, "%s: not compiled with SASL support\n",
367                         prog );
368                 return( EXIT_FAILURE );
369 #endif
370                 break;
371         case 'v':       /* verbose mode */
372             verbose++;
373             break;
374         case 'w':       /* password */
375             passwd.bv_val = strdup( optarg );
376                 {
377                         char* p;
378
379                         for( p = optarg; *p == '\0'; p++ ) {
380                                 *p = '\0';
381                         }
382                 }
383                 passwd.bv_len = strlen( passwd.bv_val );
384             break;
385         case 'W':
386                 want_bindpw++;
387                 break;
388         case 'Y':
389 #ifdef HAVE_CYRUS_SASL
390                 if( sasl_mech != NULL ) {
391                         fprintf( stderr, "%s: -Y previously specified\n", prog );
392                         return EXIT_FAILURE;
393                 }
394                 if( version == LDAP_VERSION2 ) {
395                         fprintf( stderr, "%s: -Y incompatible with version %d\n",
396                                 prog, version );
397                         return EXIT_FAILURE;
398                 }
399                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
400                         fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
401                         return EXIT_FAILURE;
402                 }
403                 authmethod = LDAP_AUTH_SASL;
404                 version = LDAP_VERSION3;
405                 sasl_mech = strdup( optarg );
406 #else
407                 fprintf( stderr, "%s: not compiled with SASL support\n",
408                         prog );
409                 return( EXIT_FAILURE );
410 #endif
411                 break;
412         case 'x':
413                 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
414                         fprintf( stderr, "%s: incompatible with previous "
415                                 "authentication choice\n", prog );
416                         return EXIT_FAILURE;
417                 }
418                 authmethod = LDAP_AUTH_SIMPLE;
419                 break;
420         case 'X':
421 #ifdef HAVE_CYRUS_SASL
422                 if( sasl_authz_id != NULL ) {
423                         fprintf( stderr, "%s: -X previously specified\n", prog );
424                         return EXIT_FAILURE;
425                 }
426                 if( version == LDAP_VERSION2 ) {
427                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
428                                 prog, version );
429                         return EXIT_FAILURE;
430                 }
431                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
432                         fprintf( stderr, "%s: -X incompatible with "
433                                 "authentication choice\n", prog );
434                         return EXIT_FAILURE;
435                 }
436                 authmethod = LDAP_AUTH_SASL;
437                 version = LDAP_VERSION3;
438                 sasl_authz_id = strdup( optarg );
439 #else
440                 fprintf( stderr, "%s: not compiled with SASL support\n",
441                         prog );
442                 return( EXIT_FAILURE );
443 #endif
444                 break;
445         case 'Z':
446 #ifdef HAVE_TLS
447                 if( version == LDAP_VERSION2 ) {
448                         fprintf( stderr, "%s: -Z incompatible with version %d\n",
449                                 prog, version );
450                         return EXIT_FAILURE;
451                 }
452                 version = LDAP_VERSION3;
453                 use_tls++;
454 #else
455                 fprintf( stderr, "%s: not compiled with TLS support\n",
456                         prog );
457                 return( EXIT_FAILURE );
458 #endif
459                 break;
460         default:
461                 fprintf( stderr, "%s: unrecongized option -%c\n",
462                         prog, optopt );
463                 usage( prog );
464                 return( EXIT_FAILURE );
465         }
466     }
467
468         if (version == -1) {
469                 version = LDAP_VERSION3;
470         }
471         if (authmethod == -1 && version > LDAP_VERSION2) {
472 #ifdef HAVE_CYRUS_SASL
473                 authmethod = LDAP_AUTH_SASL;
474 #else
475                 authmethod = LDAP_AUTH_SIMPLE;
476 #endif
477         }
478
479     if ( fp == NULL ) {
480         if ( optind >= argc ) {
481             fp = stdin;
482         }
483     }
484
485         if ( debug ) {
486                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
487                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
488                 }
489                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
490                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
491                 }
492         }
493
494 #ifdef SIGPIPE
495         (void) SIGNAL( SIGPIPE, SIG_IGN );
496 #endif
497
498         if( ( ldaphost != NULL || ldapport ) && ( ldapuri == NULL ) ) {
499                 if ( verbose ) {
500                         fprintf( stderr, "ldap_init( %s, %d )\n",
501                                 ldaphost != NULL ? ldaphost : "<DEFAULT>",
502                                 ldapport );
503                 }
504
505                 ld = ldap_init( ldaphost, ldapport );
506                 if( ld == NULL ) {
507                         perror("ldapsearch: ldap_init");
508                         return EXIT_FAILURE;
509                 }
510
511         } else {
512                 if ( verbose ) {
513                         fprintf( stderr, "ldap_initialize( %s )\n",
514                                 ldapuri != NULL ? ldapuri : "<DEFAULT>" );
515                 }
516
517                 rc = ldap_initialize( &ld, ldapuri );
518                 if( rc != LDAP_SUCCESS ) {
519                         fprintf( stderr, "Could not create LDAP session handle (%d): %s\n",
520                                 rc, ldap_err2string(rc) );
521                         return EXIT_FAILURE;
522                 }
523         }
524
525         {
526                 /* this seems prudent for searches below */
527                 int deref = LDAP_DEREF_NEVER;
528                 ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
529         }
530
531         /* chase referrals */
532         if( ldap_set_option( ld, LDAP_OPT_REFERRALS,
533                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
534         {
535                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
536                         referrals ? "on" : "off" );
537                 return EXIT_FAILURE;
538         }
539
540         if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version )
541                 != LDAP_OPT_SUCCESS )
542         {
543                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
544                         version );
545                 return EXIT_FAILURE;
546         }
547
548         if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
549                 if ( use_tls > 1 ) {
550                         ldap_perror( ld, "ldap_start_tls" );
551                         return EXIT_FAILURE;
552                 }
553                 fprintf( stderr, "WARNING: could not start TLS\n" );
554         }
555
556         if (want_bindpw) {
557                 passwd.bv_val = getpassphrase("Enter LDAP Password: ");
558                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
559         }
560
561         if ( authmethod == LDAP_AUTH_SASL ) {
562 #ifdef HAVE_CYRUS_SASL
563                 void *defaults;
564
565                 if( sasl_secprops != NULL ) {
566                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
567                                 (void *) sasl_secprops );
568                         
569                         if( rc != LDAP_OPT_SUCCESS ) {
570                                 fprintf( stderr,
571                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
572                                         sasl_secprops );
573                                 return( EXIT_FAILURE );
574                         }
575                 }
576                 
577                 defaults = lutil_sasl_defaults( ld,
578                         sasl_mech,
579                         sasl_realm,
580                         sasl_authc_id,
581                         passwd.bv_val,
582                         sasl_authz_id );
583
584                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
585                         sasl_mech, NULL, NULL,
586                         sasl_flags, lutil_sasl_interact, defaults );
587
588                 if( rc != LDAP_SUCCESS ) {
589                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
590                         return( EXIT_FAILURE );
591                 }
592 #else
593                 fprintf( stderr, "%s: not compiled with SASL support\n",
594                         argv[0] );
595                 return( EXIT_FAILURE );
596 #endif
597         }
598         else {
599                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
600                                 != LDAP_SUCCESS ) {
601                         ldap_perror( ld, "ldap_bind" );
602                         return( EXIT_FAILURE );
603                 }
604         }
605
606         if ( manageDSAit ) {
607                 int err;
608                 LDAPControl c;
609                 LDAPControl *ctrls[2];
610                 ctrls[0] = &c;
611                 ctrls[1] = NULL;
612
613                 c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
614                 c.ldctl_value.bv_val = NULL;
615                 c.ldctl_value.bv_len = 0;
616                 c.ldctl_iscritical = manageDSAit > 1;
617
618                 err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, ctrls );
619
620                 if( err != LDAP_OPT_SUCCESS ) {
621                         fprintf( stderr, "Could not set ManageDSAit %scontrol\n",
622                                 c.ldctl_iscritical ? "critical " : "" );
623                         if( c.ldctl_iscritical ) {
624                                 exit( EXIT_FAILURE );
625                         }
626                 }
627         }
628
629         rc = 0;
630     if ( fp == NULL ) {
631         for ( ; optind < argc; ++optind ) {
632             rc = dodelete( ld, argv[ optind ] );
633         }
634     } else {
635         while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
636             buf[ strlen( buf ) - 1 ] = '\0';    /* remove trailing newline */
637             if ( *buf != '\0' ) {
638                 rc = dodelete( ld, buf );
639             }
640         }
641     }
642
643     ldap_unbind( ld );
644
645         return( rc );
646 }
647
648
649 static int dodelete(
650     LDAP        *ld,
651     const char  *dn)
652 {
653         int id;
654         int     rc, code;
655         char *matcheddn = NULL, *text = NULL, **refs = NULL;
656         LDAPMessage *res;
657
658         if ( verbose ) {
659                 printf( "%sdeleting entry \"%s\"\n",
660                         (not ? "!" : ""), dn );
661         }
662
663         if ( not ) {
664                 return LDAP_SUCCESS;
665         }
666
667         /* If prune is on, remove a whole subtree.  Delete the children of the
668          * DN recursively, then the DN requested.
669          */
670         if ( prune ) deletechildren( ld, dn );
671
672         rc = ldap_delete_ext( ld, dn, NULL, NULL, &id );
673         if ( rc != LDAP_SUCCESS ) {
674                 fprintf( stderr, "%s: ldap_delete_ext: %s (%d)\n",
675                         prog, ldap_err2string( rc ), rc );
676                 return rc;
677         }
678
679         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
680         if ( rc < 0 ) {
681                 ldap_perror( ld, "ldapdelete: ldap_result" );
682                 return rc;
683         }
684
685         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
686
687         if( rc != LDAP_SUCCESS ) {
688                 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
689                         prog, ldap_err2string( rc ), rc );
690                 return rc;
691         }
692
693         if( verbose || code != LDAP_SUCCESS ||
694                 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
695         {
696                 printf( "Delete Result: %s (%d)\n", ldap_err2string( code ), code );
697
698                 if( text && *text ) {
699                         printf( "Additional info: %s\n", text );
700                 }
701
702                 if( matcheddn && *matcheddn ) {
703                         printf( "Matched DN: %s\n", matcheddn );
704                 }
705
706                 if( refs ) {
707                         int i;
708                         for( i=0; refs[i]; i++ ) {
709                                 printf("Referral: %s\n", refs[i] );
710                         }
711                 }
712         }
713
714         ber_memfree( text );
715         ber_memfree( matcheddn );
716         ber_memvfree( (void **) refs );
717
718         return code;
719 }
720
721 /*
722  * Delete all the children of an entry recursively until leaf nodes are reached.
723  *
724  */
725 static int deletechildren(
726         LDAP *ld,
727         const char *dn )
728 {
729         LDAPMessage *res, *e;
730         int entries;
731         int rc;
732         static char *attrs[] = { "1.1", NULL };
733
734         if ( verbose ) printf ( "deleting children of: %s\n", dn );
735         /*
736          * Do a one level search at dn for children.  For each, delete its children.
737          */
738
739         rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1,
740                 NULL, NULL, NULL, -1, &res );
741         if ( rc != LDAP_SUCCESS ) {
742                 ldap_perror( ld, "ldap_search" );
743                 return( rc );
744         }
745
746         entries = ldap_count_entries( ld, res );
747
748         if ( entries > 0 ) {
749                 int i;
750
751                 for (e = ldap_first_entry( ld, res ), i = 0; e != NULL;
752                         e = ldap_next_entry( ld, e ), i++ )
753                 {
754                         char *dn = ldap_get_dn( ld, e );
755
756                         if( dn == NULL ) {
757                                 ldap_perror( ld, "ldap_prune" );
758                                 ldap_get_option( ld, LDAP_OPT_ERROR_NUMBER, &rc );
759                                 ber_memfree( dn );
760                                 return rc;
761                         }
762
763                         rc = deletechildren( ld, dn );
764                         if ( rc == -1 ) {
765                                 ldap_perror( ld, "ldap_prune" );
766                                 ber_memfree( dn );
767                                 return rc;
768                         }
769
770                         if ( verbose ) {
771                                 printf( "\tremoving %s\n", dn );
772                         }
773
774                         rc = ldap_delete_s( ld, dn );
775                         if ( rc == -1 ) {
776                                 ldap_perror( ld, "ldap_delete" );
777                                 ber_memfree( dn );
778                                 return rc;
779
780                         }
781                         
782                         if ( verbose ) {
783                                 printf( "\t%s removed\n", dn );
784                         }
785
786                         ber_memfree( dn );
787                 }
788         }
789
790         ldap_msgfree( res );
791         return rc;
792 }