1 /* ldapdelete.c - simple program to delete an entry using LDAP */
2 /* $OpenLDAP: pkg/ldap/clients/tools/ldapdelete.c,v 1.118.2.7 2008/02/12 00:32:01 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
6 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
17 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms are permitted
21 * provided that this notice is preserved and that due credit is given
22 * to the University of Michigan at Ann Arbor. The name of the
23 * University may not be used to endorse or promote products derived
24 * from this software without specific prior written permission. This
25 * software is provided ``as is'' without express or implied warranty.
28 * This work was originally developed by the University of Michigan
29 * (as part of U-MICH LDAP). Additional significant contributors
38 #include <ac/stdlib.h>
40 #include <ac/string.h>
41 #include <ac/unistd.h>
42 #include <ac/socket.h>
47 #include "lutil_ldap.h"
48 #include "ldap_defaults.h"
54 static int sizelimit
= -1;
57 static int dodelete
LDAP_P((
61 static int deletechildren
LDAP_P((
69 fprintf( stderr
, _("Delete entries from an LDAP server\n\n"));
70 fprintf( stderr
, _("usage: %s [options] [dn]...\n"), prog
);
71 fprintf( stderr
, _(" dn: list of DNs to delete. If not given, it will be readed from stdin\n"));
72 fprintf( stderr
, _(" or from the file specified with \"-f file\".\n"));
73 fprintf( stderr
, _("Delete Options:\n"));
74 fprintf( stderr
, _(" -r delete recursively\n"));
80 const char options
[] = "r"
81 "cd:D:e:f:h:H:IMnO:o:p:P:QR:U:vVw:WxX:y:Y:z:Z";
84 handle_private_option( int i
)
91 char *control
, *cvalue
;
92 case 'E': /* delete extensions */
93 if( protocol
== LDAP_VERSION2
) {
94 fprintf( stderr
, _("%s: -E incompatible with LDAPv%d\n"),
99 /* should be extended to support comma separated list of
100 * [!]key[=value] parameters, e.g. -E !foo,bar=567
105 if( optarg
[0] == '!' ) {
110 control
= strdup( optarg
);
111 if ( (cvalue
= strchr( control
, '=' )) != NULL
) {
114 fprintf( stderr
, _("Invalid delete extension name: %s\n"), control
);
122 case 'z': /* size limit */
123 if ( strcasecmp( optarg
, "none" ) == 0 ) {
126 } else if ( strcasecmp( optarg
, "max" ) == 0 ) {
127 sizelimit
= LDAP_MAXINT
;
130 ival
= strtol( optarg
, &next
, 10 );
131 if ( next
== NULL
|| next
[0] != '\0' ) {
133 _("Unable to parse size limit \"%s\"\n"), optarg
);
134 exit( EXIT_FAILURE
);
138 if( sizelimit
< 0 || sizelimit
> LDAP_MAXINT
) {
139 fprintf( stderr
, _("%s: invalid sizelimit (%d) specified\n"),
141 exit( EXIT_FAILURE
);
153 private_conn_setup( LDAP
*ld
)
155 /* this seems prudent for searches below */
156 int deref
= LDAP_DEREF_NEVER
;
157 ldap_set_option( ld
, LDAP_OPT_DEREF
, &deref
);
162 main( int argc
, char **argv
)
171 tool_init( TOOL_DELETE
);
172 prog
= lutil_progname( "ldapdelete", argc
, argv
);
174 tool_args( argc
, argv
);
176 if ( infile
!= NULL
) {
177 if (( fp
= fopen( infile
, "r" )) == NULL
) {
179 exit( EXIT_FAILURE
);
182 if ( optind
>= argc
) {
187 ld
= tool_conn_setup( 0, &private_conn_setup
);
189 if ( pw_file
|| want_bindpw
) {
191 rc
= lutil_get_filed_password( pw_file
, &passwd
);
192 if( rc
) return EXIT_FAILURE
;
194 passwd
.bv_val
= getpassphrase( _("Enter LDAP Password: ") );
195 passwd
.bv_len
= passwd
.bv_val
? strlen( passwd
.bv_val
) : 0;
201 tool_server_controls( ld
, NULL
, 0 );
206 for ( ; optind
< argc
; ++optind
) {
207 rc
= dodelete( ld
, argv
[ optind
] );
209 /* Stop on error and no -c option */
212 if( contoper
== 0 ) break;
216 while ((rc
== 0 || contoper
) && fgets(buf
, sizeof(buf
), fp
) != NULL
) {
217 buf
[ strlen( buf
) - 1 ] = '\0'; /* remove trailing newline */
219 if ( *buf
!= '\0' ) {
220 rc
= dodelete( ld
, buf
);
239 char *matcheddn
= NULL
, *text
= NULL
, **refs
= NULL
;
240 LDAPControl
**ctrls
= NULL
;
245 printf( _("%sdeleting entry \"%s\"\n"),
246 (dont
? "!" : ""), dn
);
253 /* If prune is on, remove a whole subtree. Delete the children of the
254 * DN recursively, then the DN requested.
258 deletechildren( ld
, dn
, subentries
);
261 rc
= ldap_delete_ext( ld
, dn
, NULL
, NULL
, &id
);
262 if ( rc
!= LDAP_SUCCESS
) {
263 fprintf( stderr
, "%s: ldap_delete_ext: %s (%d)\n",
264 prog
, ldap_err2string( rc
), rc
);
271 if ( tool_check_abandon( ld
, id
) ) {
272 return LDAP_CANCELLED
;
278 rc
= ldap_result( ld
, LDAP_RES_ANY
, LDAP_MSG_ALL
, &tv
, &res
);
280 tool_perror( "ldap_result", rc
, NULL
, NULL
, NULL
, NULL
);
289 rc
= ldap_parse_result( ld
, res
, &code
, &matcheddn
, &text
, &refs
, &ctrls
, 1 );
295 case LDAP_NOT_ALLOWED_ON_NONLEAF
:
296 if ( prune
&& !subentries
) {
303 fprintf( stderr
, "%s: ldap_parse_result: %s (%d)\n",
304 prog
, ldap_err2string( rc
), rc
);
308 if( code
!= LDAP_SUCCESS
) {
309 tool_perror( "ldap_delete", code
, NULL
, matcheddn
, text
, refs
);
310 } else if ( verbose
&&
311 ((matcheddn
&& *matcheddn
) || (text
&& *text
) || (refs
&& *refs
) ))
313 printf( _("Delete Result: %s (%d)\n"),
314 ldap_err2string( code
), code
);
316 if( text
&& *text
) {
317 printf( _("Additional info: %s\n"), text
);
320 if( matcheddn
&& *matcheddn
) {
321 printf( _("Matched DN: %s\n"), matcheddn
);
326 for( i
=0; refs
[i
]; i
++ ) {
327 printf(_("Referral: %s\n"), refs
[i
] );
333 tool_print_ctrls( ld
, ctrls
);
334 ldap_controls_free( ctrls
);
338 ber_memfree( matcheddn
);
339 ber_memvfree( (void **) refs
);
345 * Delete all the children of an entry recursively until leaf nodes are reached.
347 static int deletechildren(
352 LDAPMessage
*res
, *e
;
354 int rc
= LDAP_SUCCESS
, srch_rc
;
355 static char *attrs
[] = { LDAP_NO_ATTRS
, NULL
};
356 LDAPControl c
, *ctrls
[2], **ctrlsp
= NULL
;
357 BerElement
*ber
= NULL
;
359 if ( verbose
) printf ( _("deleting children of: %s\n"), base
);
363 * Do a one level search at base for subentry children.
366 if ((ber
= ber_alloc_t(LBER_USE_DER
)) == NULL
) {
369 rc
= ber_printf( ber
, "b", 1 );
372 fprintf( stderr
, _("Subentries control encoding error!\n"));
375 if ( ber_flatten2( ber
, &c
.ldctl_value
, 0 ) == -1 ) {
378 c
.ldctl_oid
= LDAP_CONTROL_SUBENTRIES
;
379 c
.ldctl_iscritical
= 1;
386 * Do a one level search at base for children. For each, delete its children.
389 srch_rc
= ldap_search_ext_s( ld
, base
, LDAP_SCOPE_ONELEVEL
, NULL
, attrs
, 1,
390 ctrlsp
, NULL
, NULL
, sizelimit
, &res
);
393 case LDAP_SIZELIMIT_EXCEEDED
:
396 tool_perror( "ldap_search", srch_rc
, NULL
, NULL
, NULL
, NULL
);
400 entries
= ldap_count_entries( ld
, res
);
405 for (e
= ldap_first_entry( ld
, res
), i
= 0; e
!= NULL
;
406 e
= ldap_next_entry( ld
, e
), i
++ )
408 char *dn
= ldap_get_dn( ld
, e
);
411 ldap_get_option( ld
, LDAP_OPT_RESULT_CODE
, &rc
);
412 tool_perror( "ldap_prune", rc
, NULL
, NULL
, NULL
, NULL
);
417 rc
= deletechildren( ld
, dn
, 0 );
418 if ( rc
!= LDAP_SUCCESS
) {
419 tool_perror( "ldap_prune", rc
, NULL
, NULL
, NULL
, NULL
);
425 printf( _("\tremoving %s\n"), dn
);
428 rc
= ldap_delete_ext_s( ld
, dn
, NULL
, NULL
);
429 if ( rc
!= LDAP_SUCCESS
) {
430 tool_perror( "ldap_delete", rc
, NULL
, NULL
, NULL
, NULL
);
437 printf( _("\t%s removed\n"), dn
);
446 if ( srch_rc
== LDAP_SIZELIMIT_EXCEEDED
) {