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