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