]> git.sur5r.net Git - openldap/blob - clients/tools/ldapdelete.c
Revert previous commit
[openldap] / clients / tools / ldapdelete.c
1 /* ldapdelete.c - simple program to delete an entry using LDAP */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 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 #include <ac/string.h>
15 #include <ac/unistd.h>
16
17 #include <ldap.h>
18 #include "lutil.h"
19 #include "lutil_ldap.h"
20 #include "ldap_defaults.h"
21
22 #include "common.h"
23
24
25 static int      prune = 0;
26
27
28 static int dodelete LDAP_P((
29     LDAP *ld,
30     const char *dn));
31
32 static int deletechildren LDAP_P((
33         LDAP *ld,
34         const char *dn ));
35
36 void
37 usage( void )
38 {
39         fprintf( stderr,
40 "Delete entries from an LDAP server\n\n"
41 "usage: %s [options] [dn]...\n"
42 "       dn: list of DNs to delete. If not given, it will be readed from stdin\n"
43 "           or from the file specified with \"-f file\".\n"
44 "Delete Options:\n"
45 "  -r         delete recursively\n"
46                          , prog );
47         tool_common_usage();
48         exit( EXIT_FAILURE );
49 }
50
51
52 const char options[] = "r"
53         "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vVw:WxX:y:Y:Z";
54
55 int
56 handle_private_option( int i )
57 {
58         switch ( i ) {
59 #if 0
60                 int crit;
61                 char *control, *cvalue;
62         case 'E': /* delete controls */
63                 if( protocol == LDAP_VERSION2 ) {
64                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
65                                 prog, protocol );
66                         exit( EXIT_FAILURE );
67                 }
68
69                 /* should be extended to support comma separated list of
70                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
71                  */
72
73                 crit = 0;
74                 cvalue = NULL;
75                 if( optarg[0] == '!' ) {
76                         crit = 1;
77                         optarg++;
78                 }
79
80                 control = strdup( optarg );
81                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
82                         *cvalue++ = '\0';
83                 }
84                 fprintf( stderr, "Invalid delete control name: %s\n", control );
85                 usage();
86 #endif
87
88         case 'r':
89                 prune = 1;
90                 break;
91
92         default:
93                 return 0;
94         }
95         return 1;
96 }
97
98
99 static void
100 private_conn_setup( LDAP *ld )
101 {
102         /* this seems prudent for searches below */
103         int deref = LDAP_DEREF_NEVER;
104         ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
105 }
106
107
108 int
109 main( int argc, char **argv )
110 {
111         char            buf[ 4096 ];
112         FILE            *fp;
113         LDAP            *ld;
114         int             rc, retval;
115
116     fp = NULL;
117
118     prog = lutil_progname( "ldapdelete", argc, argv );
119
120         tool_args( argc, argv );
121
122         if ( infile != NULL ) {
123                 if (( fp = fopen( infile, "r" )) == NULL ) {
124                         perror( optarg );
125                         exit( EXIT_FAILURE );
126             }
127         } else {
128         if ( optind >= argc ) {
129             fp = stdin;
130         }
131     }
132
133         ld = tool_conn_setup( 0, &private_conn_setup );
134
135         if ( pw_file || want_bindpw ) {
136                 if ( pw_file ) {
137                         rc = lutil_get_filed_password( pw_file, &passwd );
138                         if( rc ) return EXIT_FAILURE;
139                 } else {
140                         passwd.bv_val = getpassphrase( "Enter LDAP Password: " );
141                         passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
142                 }
143         }
144
145         tool_bind( ld );
146
147         if ( authzid || manageDSAit || noop )
148                 tool_server_controls( ld, NULL, 0 );
149
150         retval = rc = 0;
151
152     if ( fp == NULL ) {
153                 for ( ; optind < argc; ++optind ) {
154                         rc = dodelete( ld, argv[ optind ] );
155
156                         /* Stop on error and no -c option */
157                         if( rc != 0 ) {
158                                 retval = rc;
159                                 if( contoper == 0 ) break;
160                         }
161                 }
162         } else {
163                 while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
164                         buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
165
166                         if ( *buf != '\0' ) {
167                                 rc = dodelete( ld, buf );
168                                 if ( rc != 0 )
169                                         retval = rc;
170                         }
171                 }
172         }
173
174     ldap_unbind( ld );
175
176     return( retval );
177 }
178
179
180 static int dodelete(
181     LDAP        *ld,
182     const char  *dn)
183 {
184         int id;
185         int     rc, code;
186         char *matcheddn = NULL, *text = NULL, **refs = NULL;
187         LDAPMessage *res;
188
189         if ( verbose ) {
190                 printf( "%sdeleting entry \"%s\"\n",
191                         (not ? "!" : ""), dn );
192         }
193
194         if ( not ) {
195                 return LDAP_SUCCESS;
196         }
197
198         /* If prune is on, remove a whole subtree.  Delete the children of the
199          * DN recursively, then the DN requested.
200          */
201         if ( prune ) deletechildren( ld, dn );
202
203         rc = ldap_delete_ext( ld, dn, NULL, NULL, &id );
204         if ( rc != LDAP_SUCCESS ) {
205                 fprintf( stderr, "%s: ldap_delete_ext: %s (%d)\n",
206                         prog, ldap_err2string( rc ), rc );
207                 return rc;
208         }
209
210         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
211         if ( rc < 0 ) {
212                 ldap_perror( ld, "ldapdelete: ldap_result" );
213                 return rc;
214         }
215
216         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
217
218         if( rc != LDAP_SUCCESS ) {
219                 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
220                         prog, ldap_err2string( rc ), rc );
221                 return rc;
222         }
223
224         if( verbose || code != LDAP_SUCCESS ||
225                 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
226         {
227                 printf( "Delete Result: %s (%d)\n", ldap_err2string( code ), code );
228
229                 if( text && *text ) {
230                         printf( "Additional info: %s\n", text );
231                 }
232
233                 if( matcheddn && *matcheddn ) {
234                         printf( "Matched DN: %s\n", matcheddn );
235                 }
236
237                 if( refs ) {
238                         int i;
239                         for( i=0; refs[i]; i++ ) {
240                                 printf("Referral: %s\n", refs[i] );
241                         }
242                 }
243         }
244
245         ber_memfree( text );
246         ber_memfree( matcheddn );
247         ber_memvfree( (void **) refs );
248
249         return code;
250 }
251
252 /*
253  * Delete all the children of an entry recursively until leaf nodes are reached.
254  *
255  */
256 static int deletechildren(
257         LDAP *ld,
258         const char *dn )
259 {
260         LDAPMessage *res, *e;
261         int entries;
262         int rc;
263         static char *attrs[] = { "1.1", NULL };
264
265         if ( verbose ) printf ( "deleting children of: %s\n", dn );
266         /*
267          * Do a one level search at dn for children.  For each, delete its children.
268          */
269
270         rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1,
271                 NULL, NULL, NULL, -1, &res );
272         if ( rc != LDAP_SUCCESS ) {
273                 ldap_perror( ld, "ldap_search" );
274                 return( rc );
275         }
276
277         entries = ldap_count_entries( ld, res );
278
279         if ( entries > 0 ) {
280                 int i;
281
282                 for (e = ldap_first_entry( ld, res ), i = 0; e != NULL;
283                         e = ldap_next_entry( ld, e ), i++ )
284                 {
285                         char *dn = ldap_get_dn( ld, e );
286
287                         if( dn == NULL ) {
288                                 ldap_perror( ld, "ldap_prune" );
289                                 ldap_get_option( ld, LDAP_OPT_ERROR_NUMBER, &rc );
290                                 ber_memfree( dn );
291                                 return rc;
292                         }
293
294                         rc = deletechildren( ld, dn );
295                         if ( rc == -1 ) {
296                                 ldap_perror( ld, "ldap_prune" );
297                                 ber_memfree( dn );
298                                 return rc;
299                         }
300
301                         if ( verbose ) {
302                                 printf( "\tremoving %s\n", dn );
303                         }
304
305                         rc = ldap_delete_s( ld, dn );
306                         if ( rc == -1 ) {
307                                 ldap_perror( ld, "ldap_delete" );
308                                 ber_memfree( dn );
309                                 return rc;
310
311                         }
312                         
313                         if ( verbose ) {
314                                 printf( "\t%s removed\n", dn );
315                         }
316
317                         ber_memfree( dn );
318                 }
319         }
320
321         ldap_msgfree( res );
322         return rc;
323 }