]> git.sur5r.net Git - openldap/blob - clients/tools/ldapdelete.c
Happy new year
[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" "cCd:D:e:f:h:H:IkKMnO:p:P:QR:U:vw:WxX:y:Y:Z";
53
54 int
55 handle_private_option( int i )
56 {
57         switch ( i ) {
58 #if 0
59                 int crit;
60                 char *control, *cvalue;
61         case 'E': /* delete controls */
62                 if( version == LDAP_VERSION2 ) {
63                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
64                                 prog, version );
65                         exit( EXIT_FAILURE );
66                 }
67
68                 /* should be extended to support comma separated list of
69                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
70                  */
71
72                 crit = 0;
73                 cvalue = NULL;
74                 if( optarg[0] == '!' ) {
75                         crit = 1;
76                         optarg++;
77                 }
78
79                 control = strdup( optarg );
80                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
81                         *cvalue++ = '\0';
82                 }
83                 fprintf( stderr, "Invalid delete control name: %s\n", control );
84                 usage();
85 #endif
86
87         case 'r':
88                 prune = 1;
89                 break;
90
91         default:
92                 return 0;
93         }
94         return 1;
95 }
96
97
98 static void
99 private_conn_setup( LDAP *ld )
100 {
101         /* this seems prudent for searches below */
102         int deref = LDAP_DEREF_NEVER;
103         ldap_set_option( ld, LDAP_OPT_DEREF, &deref );
104 }
105
106
107 int
108 main( int argc, char **argv )
109 {
110         char            buf[ 4096 ];
111         FILE            *fp;
112         LDAP            *ld;
113         int             rc, retval;
114
115     fp = NULL;
116
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 ( authzid || manageDSAit || noop )
147                 tool_server_controls( ld, NULL, 0 );
148
149         retval = rc = 0;
150
151     if ( fp == NULL ) {
152                 for ( ; optind < argc; ++optind ) {
153                         rc = dodelete( ld, argv[ optind ] );
154
155                         /* Stop on error and no -c option */
156                         if( rc != 0 ) {
157                                 retval = rc;
158                                 if( contoper == 0 ) break;
159                         }
160                 }
161         } else {
162                 while ((rc == 0 || contoper) && fgets(buf, sizeof(buf), fp) != NULL) {
163                         buf[ strlen( buf ) - 1 ] = '\0'; /* remove trailing newline */
164
165                         if ( *buf != '\0' ) {
166                                 rc = dodelete( ld, buf );
167                                 if ( rc != 0 )
168                                         retval = rc;
169                         }
170                 }
171         }
172
173     ldap_unbind( ld );
174
175     return( retval );
176 }
177
178
179 static int dodelete(
180     LDAP        *ld,
181     const char  *dn)
182 {
183         int id;
184         int     rc, code;
185         char *matcheddn = NULL, *text = NULL, **refs = NULL;
186         LDAPMessage *res;
187
188         if ( verbose ) {
189                 printf( "%sdeleting entry \"%s\"\n",
190                         (not ? "!" : ""), dn );
191         }
192
193         if ( not ) {
194                 return LDAP_SUCCESS;
195         }
196
197         /* If prune is on, remove a whole subtree.  Delete the children of the
198          * DN recursively, then the DN requested.
199          */
200         if ( prune ) deletechildren( ld, dn );
201
202         rc = ldap_delete_ext( ld, dn, NULL, NULL, &id );
203         if ( rc != LDAP_SUCCESS ) {
204                 fprintf( stderr, "%s: ldap_delete_ext: %s (%d)\n",
205                         prog, ldap_err2string( rc ), rc );
206                 return rc;
207         }
208
209         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
210         if ( rc < 0 ) {
211                 ldap_perror( ld, "ldapdelete: ldap_result" );
212                 return rc;
213         }
214
215         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 );
216
217         if( rc != LDAP_SUCCESS ) {
218                 fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n",
219                         prog, ldap_err2string( rc ), rc );
220                 return rc;
221         }
222
223         if( verbose || code != LDAP_SUCCESS ||
224                 (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) )
225         {
226                 printf( "Delete Result: %s (%d)\n", ldap_err2string( code ), code );
227
228                 if( text && *text ) {
229                         printf( "Additional info: %s\n", text );
230                 }
231
232                 if( matcheddn && *matcheddn ) {
233                         printf( "Matched DN: %s\n", matcheddn );
234                 }
235
236                 if( refs ) {
237                         int i;
238                         for( i=0; refs[i]; i++ ) {
239                                 printf("Referral: %s\n", refs[i] );
240                         }
241                 }
242         }
243
244         ber_memfree( text );
245         ber_memfree( matcheddn );
246         ber_memvfree( (void **) refs );
247
248         return code;
249 }
250
251 /*
252  * Delete all the children of an entry recursively until leaf nodes are reached.
253  *
254  */
255 static int deletechildren(
256         LDAP *ld,
257         const char *dn )
258 {
259         LDAPMessage *res, *e;
260         int entries;
261         int rc;
262         static char *attrs[] = { "1.1", NULL };
263
264         if ( verbose ) printf ( "deleting children of: %s\n", dn );
265         /*
266          * Do a one level search at dn for children.  For each, delete its children.
267          */
268
269         rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_ONELEVEL, NULL, attrs, 1,
270                 NULL, NULL, NULL, -1, &res );
271         if ( rc != LDAP_SUCCESS ) {
272                 ldap_perror( ld, "ldap_search" );
273                 return( rc );
274         }
275
276         entries = ldap_count_entries( ld, res );
277
278         if ( entries > 0 ) {
279                 int i;
280
281                 for (e = ldap_first_entry( ld, res ), i = 0; e != NULL;
282                         e = ldap_next_entry( ld, e ), i++ )
283                 {
284                         char *dn = ldap_get_dn( ld, e );
285
286                         if( dn == NULL ) {
287                                 ldap_perror( ld, "ldap_prune" );
288                                 ldap_get_option( ld, LDAP_OPT_ERROR_NUMBER, &rc );
289                                 ber_memfree( dn );
290                                 return rc;
291                         }
292
293                         rc = deletechildren( ld, dn );
294                         if ( rc == -1 ) {
295                                 ldap_perror( ld, "ldap_prune" );
296                                 ber_memfree( dn );
297                                 return rc;
298                         }
299
300                         if ( verbose ) {
301                                 printf( "\tremoving %s\n", dn );
302                         }
303
304                         rc = ldap_delete_s( ld, dn );
305                         if ( rc == -1 ) {
306                                 ldap_perror( ld, "ldap_delete" );
307                                 ber_memfree( dn );
308                                 return rc;
309
310                         }
311                         
312                         if ( verbose ) {
313                                 printf( "\t%s removed\n", dn );
314                         }
315
316                         ber_memfree( dn );
317                 }
318         }
319
320         ldap_msgfree( res );
321         return rc;
322 }