]> git.sur5r.net Git - openldap/blob - clients/tools/ldapdelete.c
7aa0b7bf5e9fb80fa0f9497e4905929f79c6bf48
[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, _("Delete entries from an LDAP server\n\n"));
40         fprintf( stderr, _("usage: %s [options] [dn]...\n"), prog);
41         fprintf( stderr, _("    dn: list of DNs to delete. If not given, it will be readed from stdin\n"));
42         fprintf( stderr, _("        or from the file specified with \"-f file\".\n"));
43         fprintf( stderr, _("Delete Options:\n"));
44         fprintf( stderr, _("  -r         delete recursively\n"));
45         tool_common_usage();
46         exit( EXIT_FAILURE );
47 }
48
49
50 const char options[] = "r"
51         "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vVw:WxX:y:Y:Z";
52
53 int
54 handle_private_option( int i )
55 {
56         switch ( i ) {
57 #if 0
58                 int crit;
59                 char *control, *cvalue;
60         case 'E': /* delete controls */
61                 if( protocol == LDAP_VERSION2 ) {
62                         fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
63                                 prog, protocol );
64                         exit( EXIT_FAILURE );
65                 }
66
67                 /* should be extended to support comma separated list of
68                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
69                  */
70
71                 crit = 0;
72                 cvalue = NULL;
73                 if( optarg[0] == '!' ) {
74                         crit = 1;
75                         optarg++;
76                 }
77
78                 control = strdup( optarg );
79                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
80                         *cvalue++ = '\0';
81                 }
82                 fprintf( stderr, _("Invalid delete control name: %s\n"), control );
83                 usage();
84 #endif
85
86         case 'r':
87                 prune = 1;
88                 break;
89
90         default:
91                 return 0;
92         }
93         return 1;
94 }
95
96
97 static void
98 private_conn_setup( LDAP *ld )
99 {
100         /* this seems prudent for searches below */
101         int deref = LDAP_DEREF_NEVER;
102         ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
103 }
104
105
106 int
107 main( int argc, char **argv )
108 {
109         char            buf[ 4096 ];
110         FILE            *fp;
111         LDAP            *ld;
112         int             rc, retval;
113
114     fp = NULL;
115
116         tool_init();
117     prog = lutil_progname( "ldapdelete", argc, argv );
118
119         tool_args( argc, argv );
120
121         if ( infile != NULL ) {
122                 if (( fp = fopen( infile, "r" )) == NULL ) {
123                         perror( optarg );
124                         exit( EXIT_FAILURE );
125             }
126         } else {
127         if ( optind >= argc ) {
128             fp = stdin;
129         }
130     }
131
132         ld = tool_conn_setup( 0, &private_conn_setup );
133
134         if ( pw_file || want_bindpw ) {
135                 if ( pw_file ) {
136                         rc = lutil_get_filed_password( pw_file, &passwd );
137                         if( rc ) return EXIT_FAILURE;
138                 } else {
139                         passwd.bv_val = getpassphrase( _("Enter LDAP Password: ") );
140                         passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
141                 }
142         }
143
144         tool_bind( ld );
145
146         if ( assertion || authzid || manageDSAit || noop ) {
147                 tool_server_controls( ld, NULL, 0 );
148         }
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 }