]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/slapcommon.c
Implement slapcat -s <dn>: Only dump a subtree of the database.
[openldap] / servers / slapd / tools / slapcommon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /* slapcommon.c - common routine for the slap tools */
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/socket.h>
16 #include <ac/unistd.h>
17
18 #include "slapcommon.h"
19 #include "lutil.h"
20
21
22 char    *progname       = NULL;
23 char    *conffile       = SLAPD_DEFAULT_CONFIGFILE;
24 int             truncatemode = 0;
25 int             verbose         = 0;
26 int             continuemode = 0;
27 int             nosubordinates = 0;
28 int             dryrun = 0;
29 struct berval   sub_ndn = { 0, NULL };
30
31 char    *ldiffile       = NULL;
32 FILE    *ldiffp         = NULL;
33
34 #ifdef CSRIMALLOC
35         char *leakfilename;
36         FILE *leakfile;
37 #endif
38
39 Backend *be = NULL;
40
41 static void
42 usage( int tool )
43 {
44         char *options = NULL;
45         fprintf( stderr,
46                 "usage: %s [-v] [-c] [-d debuglevel] [-f configfile]\n"
47                         "\t[-n databasenumber | -b suffix]", progname );
48
49         switch( tool ) {
50         case SLAPADD:
51                 options = "\t[-l ldiffile] [-u]\n";
52                 break;
53
54         case SLAPCAT:
55                 options = "\t[-l ldiffile]\n";
56                 break;
57
58         case SLAPINDEX:
59                 options = "\n";
60                 break;
61         }
62
63         if( options != NULL ) {
64                 fputs( options, stderr );
65         }
66         exit( EXIT_FAILURE );
67 }
68
69
70 /*
71  * slap_tool_init - initialize slap utility, handle program options.
72  * arguments:
73  *      name            program name
74  *      tool            tool code
75  *      argc, argv      command line arguments
76  */
77
78 void
79 slap_tool_init(
80         const char* name,
81         int tool,
82         int argc, char **argv )
83 {
84         char *options;
85         struct berval base = { 0, NULL };
86         char *subtree = NULL;
87         int rc, i, dbnum;
88         int mode = SLAP_TOOL_MODE;
89
90         progname = lutil_progname( name, argc, argv );
91
92 #ifdef CSRIMALLOC
93         leakfilename = malloc( strlen( progname ) + sizeof(".leak") );
94         sprintf( leakfilename, "%s.leak", progname );
95         if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) {
96                 leakfile = stderr;
97         }
98         free( leakfilename );
99 #endif
100
101         switch( tool ) {
102         case SLAPADD:
103                 options = "b:cd:f:l:n:tuv";
104                 break;
105
106         case SLAPINDEX:
107                 options = "b:cd:f:n:v";
108                 break;
109
110         case SLAPCAT:
111                 options = "b:cd:f:l:n:s:v";
112                 break;
113
114         default:
115                 fprintf( stderr, "%s: unknown tool mode (%d)\n",
116                          progname, tool );
117                 exit( EXIT_FAILURE );
118         }
119
120         ldiffile = NULL;
121         conffile = SLAPD_DEFAULT_CONFIGFILE;
122         dbnum = -1;
123         while ( (i = getopt( argc, argv, options )) != EOF ) {
124                 switch ( i ) {
125                 case 'b':
126                         base.bv_val = strdup( optarg );
127                         base.bv_len = strlen( base.bv_val );
128                         break;
129
130                 case 'c':       /* enable continue mode */
131                         continuemode++;
132                         break;
133
134                 case 'd':       /* turn on debugging */
135                         ldap_debug += atoi( optarg );
136                         break;
137
138                 case 'f':       /* specify a conf file */
139                         conffile = strdup( optarg );
140                         break;
141
142                 case 'l':       /* LDIF file */
143                         ldiffile = strdup( optarg );
144                         break;
145
146                 case 'n':       /* which config file db to index */
147                         dbnum = atoi( optarg ) - 1;
148                         break;
149
150                 case 's':       /* dump subtree */
151                         subtree = strdup( optarg );
152                         break;
153
154                 case 't':       /* turn on truncate */
155                         truncatemode++;
156                         mode |= SLAP_TRUNCATE_MODE;
157                         break;
158
159                 case 'u':       /* dry run */
160                         dryrun++;
161                         break;
162
163                 case 'v':       /* turn on verbose */
164                         verbose++;
165                         break;
166
167                 default:
168                         usage( tool );
169                         break;
170                 }
171         }
172
173         if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) {
174                 usage( tool );
175         }
176
177         if ( ldiffile == NULL ) {
178                 ldiffp = tool == SLAPCAT ? stdout : stdin;
179
180         } else if( (ldiffp = fopen( ldiffile, tool == SLAPCAT ? "w" : "r" ))
181                 == NULL )
182         {
183                 perror( ldiffile );
184                 exit( EXIT_FAILURE );
185         }
186
187         /*
188          * initialize stuff and figure out which backend we're dealing with
189          */
190
191 #ifdef SLAPD_MODULES
192         if ( module_init() != 0 ) {
193                 fprintf( stderr, "%s: module_init failed!\n", progname );
194                 exit( EXIT_FAILURE );
195         }
196 #endif
197                 
198         rc = slap_init( mode, progname );
199
200         if ( rc != 0 ) {
201                 fprintf( stderr, "%s: slap_init failed!\n", progname );
202                 exit( EXIT_FAILURE );
203         }
204
205         rc = slap_schema_init();
206
207         if ( rc != 0 ) {
208                 fprintf( stderr, "%s: slap_schema_init failed!\n", progname );
209                 exit( EXIT_FAILURE );
210         }
211
212         rc = read_config( conffile, 0 );
213
214         if ( rc != 0 ) {
215                 fprintf( stderr, "%s: bad configuration file!\n", progname );
216                 exit( EXIT_FAILURE );
217         }
218
219         if ( !nbackends ) {
220                 fprintf( stderr, "No databases found in config file\n" );
221                 exit( EXIT_FAILURE );
222         }
223
224         rc = glue_sub_init();
225
226         if ( rc != 0 ) {
227                 fprintf( stderr, "Subordinate configuration error\n" );
228                 exit( EXIT_FAILURE );
229         }
230
231         rc = slap_schema_check();
232
233         if ( rc != 0 ) {
234                 fprintf( stderr, "%s: slap_schema_prep failed!\n", progname );
235                 exit( EXIT_FAILURE );
236         }
237
238         if( subtree ) {
239                 struct berval val;
240                 val.bv_val = subtree;
241                 val.bv_len = strlen( subtree );
242                 rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL );
243                 if( rc != LDAP_SUCCESS ) {
244                         fprintf( stderr, "Invalid subtree DN '%s'\n", optarg );
245                         exit( EXIT_FAILURE );
246                 }
247
248                 if( base.bv_val == NULL && dbnum == -1 )
249                         base = val;
250                 else
251                         free( subtree );
252         }
253
254         if( base.bv_val != NULL ) {
255                 struct berval nbase;
256
257                 rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL );
258                 if( rc != LDAP_SUCCESS ) {
259                         fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n",
260                                 progname, base.bv_val );
261                         exit( EXIT_FAILURE );
262                 }
263
264                 be = select_backend( &nbase, 0, 0 );
265                 ber_memfree( nbase.bv_val );
266
267                 if( be == NULL ) {
268                         fprintf( stderr, "%s: slap_init no backend for \"%s\"\n",
269                                 progname, base.bv_val );
270                         exit( EXIT_FAILURE );
271                 }
272                 /* If the named base is a glue master, operate on the
273                  * entire context
274                  */
275                 if (SLAP_GLUE_INSTANCE(be)) {
276                         nosubordinates = 1;
277                 }
278
279         } else if ( dbnum == -1 ) {
280                 if ( nbackends <= 0 ) {
281                         fprintf( stderr, "No available databases\n" );
282                         exit( EXIT_FAILURE );
283                 }
284                 
285                 be = &backends[dbnum=0];
286                 /* If just doing the first by default and it is a
287                  * glue subordinate, find the master.
288                  */
289                 while (SLAP_GLUE_SUBORDINATE(be) || SLAP_MONITOR(be)) {
290                         if (SLAP_GLUE_SUBORDINATE(be)) {
291                                 nosubordinates = 1;
292                         }
293                         be++;
294                         dbnum++;
295                 }
296
297
298                 if ( dbnum >= nbackends ) {
299                         fprintf( stderr, "Available database(s) "
300                                         "do not allow %s\n", name );
301                         exit( EXIT_FAILURE );
302                 }
303                 
304                 if ( nosubordinates == 0 && dbnum > 0 ) {
305 #ifdef NEW_LOGGING
306                         LDAP_LOG( BACKEND, ERR, 
307 "The first database does not allow %s; using the first available one (%d)\n",
308                                 name, dbnum + 1, 0 );
309 #else
310                         Debug( LDAP_DEBUG_ANY,
311 "The first database does not allow %s; using the first available one (%d)\n",
312                                 name, dbnum + 1, 0 );
313 #endif
314                 }
315
316         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
317                 fprintf( stderr,
318                         "Database number selected via -n is out of range\n"
319                         "Must be in the range 1 to %d"
320                                 " (number of databases in the config file)\n",
321                         nbackends );
322                 exit( EXIT_FAILURE );
323
324         } else {
325                 be = &backends[dbnum];
326         }
327
328 #ifdef CSRIMALLOC
329         mal_leaktrace(1);
330 #endif
331
332         slap_startup( be );
333 }
334
335 void slap_tool_destroy( void )
336 {
337         slap_shutdown( be );
338         slap_destroy();
339 #ifdef SLAPD_MODULES
340         if ( slapMode == SLAP_SERVER_MODE ) {
341         /* always false. just pulls in necessary symbol references. */
342                 lutil_uuidstr(NULL, 0);
343         }
344         module_kill();
345 #endif
346         schema_destroy();
347 #ifdef HAVE_TLS
348         ldap_pvt_tls_destroy();
349 #endif
350         config_destroy();
351
352 #ifdef CSRIMALLOC
353         mal_dumpleaktrace( leakfile );
354 #endif
355 }