]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/slapcommon.c
073f2924c22117408c3d1f25b10e1d41c3286952
[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             update_ctxcsn = SLAP_TOOL_CTXCSN_KEEP;
27 int             retrieve_ctxcsn = 0;
28 int             retrieve_synccookie = 0;
29 int             replica_promotion = 0;
30 int             replica_demotion = 0;
31 char    *replica_id_string = NULL;
32 char    **replica_id_strlist = NULL;
33 int             *replica_id_list = NULL;
34 int             continuemode = 0;
35 int             nosubordinates = 0;
36 int             dryrun = 0;
37 struct berval   sub_ndn = { 0, NULL };
38
39 char    *ldiffile       = NULL;
40 FILE    *ldiffp         = NULL;
41
42 #ifdef CSRIMALLOC
43         char *leakfilename;
44         FILE *leakfile;
45 #endif
46
47 Backend *be = NULL;
48
49 static void
50 usage( int tool )
51 {
52         char *options = NULL;
53         fprintf( stderr,
54                 "usage: %s [-v] [-c] [-d debuglevel] [-f configfile]\n"
55                         "\t[-n databasenumber | -b suffix]", progname );
56
57         switch( tool ) {
58         case SLAPADD:
59                 options = "\n\t[-l ldiffile] [-u] [-p [-w] | -r [-i syncreplidlist] [-w]]\n";
60                 break;
61
62         case SLAPCAT:
63                 options = "\t[-l ldiffile] [-m] [-k]\n";
64                 break;
65
66         case SLAPINDEX:
67                 options = "\n";
68                 break;
69         }
70
71         if( options != NULL ) {
72                 fputs( options, stderr );
73         }
74         exit( EXIT_FAILURE );
75 }
76
77
78 /*
79  * slap_tool_init - initialize slap utility, handle program options.
80  * arguments:
81  *      name            program name
82  *      tool            tool code
83  *      argc, argv      command line arguments
84  */
85
86 void
87 slap_tool_init(
88         const char* name,
89         int tool,
90         int argc, char **argv )
91 {
92         char *options;
93         struct berval base = { 0, NULL };
94         char *subtree = NULL;
95         int rc, i, dbnum;
96         int mode = SLAP_TOOL_MODE;
97
98         progname = lutil_progname( name, argc, argv );
99
100 #ifdef CSRIMALLOC
101         leakfilename = malloc( strlen( progname ) + sizeof(".leak") );
102         sprintf( leakfilename, "%s.leak", progname );
103         if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) {
104                 leakfile = stderr;
105         }
106         free( leakfilename );
107 #endif
108
109         switch( tool ) {
110         case SLAPADD:
111                 options = "b:cd:f:i:l:n:prtuvWw";
112                 break;
113
114         case SLAPINDEX:
115                 options = "b:cd:f:n:v";
116                 mode |= SLAP_TOOL_READMAIN;
117                 break;
118
119         case SLAPCAT:
120                 options = "b:cd:f:kl:mn:s:v";
121                 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
122                 break;
123
124         default:
125                 fprintf( stderr, "%s: unknown tool mode (%d)\n",
126                          progname, tool );
127                 exit( EXIT_FAILURE );
128         }
129
130         ldiffile = NULL;
131         conffile = SLAPD_DEFAULT_CONFIGFILE;
132         dbnum = -1;
133         while ( (i = getopt( argc, argv, options )) != EOF ) {
134                 switch ( i ) {
135                 case 'b':
136                         base.bv_val = strdup( optarg );
137                         base.bv_len = strlen( base.bv_val );
138                         break;
139
140                 case 'c':       /* enable continue mode */
141                         continuemode++;
142                         break;
143
144                 case 'd':       /* turn on debugging */
145                         ldap_debug += atoi( optarg );
146                         break;
147
148                 case 'f':       /* specify a conf file */
149                         conffile = strdup( optarg );
150                         break;
151
152                 case 'i': /* specify syncrepl id list */
153                         replica_id_string = strdup( optarg );
154                         if ( !isdigit( *replica_id_string )) {
155                                 usage( tool );
156                                 exit( EXIT_FAILURE );
157                         }
158                         str2clist( &replica_id_strlist, replica_id_string, "," );
159                         for ( i = 0; replica_id_strlist && replica_id_strlist[i]; i++ ) ;
160                         replica_id_list = ch_calloc( i + 1, sizeof( int ) );
161                         for ( i = 0; replica_id_strlist && replica_id_strlist[i]; i++ ) {
162                                 replica_id_list[i] = atoi( replica_id_strlist[i] );
163                                 if ( replica_id_list[i] >= 1000 ) {
164                                         fprintf(stderr,
165                                                 "%s: syncrepl id %d is out of range [0..999]\n",
166                                                 progname, replica_id_list[i] );
167                                         exit( EXIT_FAILURE );
168                                 }
169                         }
170                         replica_id_list[i] = -1;
171                         break;
172
173                 case 'k':       /* Retrieve sync cookie entry */
174                         retrieve_synccookie = 1;
175                         break;
176
177                 case 'l':       /* LDIF file */
178                         ldiffile = strdup( optarg );
179                         break;
180
181                 case 'm':       /* Retrieve ldapsync entry */
182                         retrieve_ctxcsn = 1;
183                         break;
184
185                 case 'n':       /* which config file db to index */
186                         dbnum = atoi( optarg ) - 1;
187                         break;
188
189                 case 'p':       /* replica promotion */
190                         replica_promotion = 1;          
191                         break;
192
193                 case 'r':       /* replica demotion */
194                         replica_demotion = 1;           
195                         break;
196
197                 case 's':       /* dump subtree */
198                         subtree = strdup( optarg );
199                         break;
200
201                 case 't':       /* turn on truncate */
202                         truncatemode++;
203                         mode |= SLAP_TRUNCATE_MODE;
204                         break;
205
206                 case 'u':       /* dry run */
207                         dryrun++;
208                         break;
209
210                 case 'v':       /* turn on verbose */
211                         verbose++;
212                         break;
213
214                 case 'W':       /* write context csn on every entry add */
215                         update_ctxcsn = SLAP_TOOL_CTXCSN_BATCH;
216                         /* FIXME : update_ctxcsn = SLAP_TOOL_CTXCSN_ENTRY; */
217                         break;
218
219                 case 'w':       /* write context csn on at the end */
220                         update_ctxcsn = SLAP_TOOL_CTXCSN_BATCH;
221                         break;
222
223                 default:
224                         usage( tool );
225                         break;
226                 }
227         }
228
229         if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) {
230                 usage( tool );
231         }
232
233         if ( replica_promotion && replica_demotion ) {
234                 usage( tool );
235         } else if ( !replica_promotion && !replica_demotion ) {
236                 if ( update_ctxcsn != SLAP_TOOL_CTXCSN_KEEP ) {
237                         usage( tool );
238                 }
239         }
240
241         if ( ldiffile == NULL ) {
242                 ldiffp = tool == SLAPCAT ? stdout : stdin;
243
244         } else if( (ldiffp = fopen( ldiffile, tool == SLAPCAT ? "w" : "r" ))
245                 == NULL )
246         {
247                 perror( ldiffile );
248                 exit( EXIT_FAILURE );
249         }
250
251         /*
252          * initialize stuff and figure out which backend we're dealing with
253          */
254
255 #ifdef SLAPD_MODULES
256         if ( module_init() != 0 ) {
257                 fprintf( stderr, "%s: module_init failed!\n", progname );
258                 exit( EXIT_FAILURE );
259         }
260 #endif
261                 
262         rc = slap_init( mode, progname );
263
264         if ( rc != 0 ) {
265                 fprintf( stderr, "%s: slap_init failed!\n", progname );
266                 exit( EXIT_FAILURE );
267         }
268
269         rc = slap_schema_init();
270
271         if ( rc != 0 ) {
272                 fprintf( stderr, "%s: slap_schema_init failed!\n", progname );
273                 exit( EXIT_FAILURE );
274         }
275
276         rc = read_config( conffile, 0 );
277
278         if ( rc != 0 ) {
279                 fprintf( stderr, "%s: bad configuration file!\n", progname );
280                 exit( EXIT_FAILURE );
281         }
282
283         if ( !nbackends ) {
284                 fprintf( stderr, "No databases found in config file\n" );
285                 exit( EXIT_FAILURE );
286         }
287
288         rc = glue_sub_init();
289
290         if ( rc != 0 ) {
291                 fprintf( stderr, "Subordinate configuration error\n" );
292                 exit( EXIT_FAILURE );
293         }
294
295         rc = slap_schema_check();
296
297         if ( rc != 0 ) {
298                 fprintf( stderr, "%s: slap_schema_prep failed!\n", progname );
299                 exit( EXIT_FAILURE );
300         }
301
302         if( subtree ) {
303                 struct berval val;
304                 val.bv_val = subtree;
305                 val.bv_len = strlen( subtree );
306                 rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL );
307                 if( rc != LDAP_SUCCESS ) {
308                         fprintf( stderr, "Invalid subtree DN '%s'\n", optarg );
309                         exit( EXIT_FAILURE );
310                 }
311
312                 if( base.bv_val == NULL && dbnum == -1 )
313                         base = val;
314                 else
315                         free( subtree );
316         }
317
318         if( base.bv_val != NULL ) {
319                 struct berval nbase;
320
321                 rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL );
322                 if( rc != LDAP_SUCCESS ) {
323                         fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n",
324                                 progname, base.bv_val );
325                         exit( EXIT_FAILURE );
326                 }
327
328                 be = select_backend( &nbase, 0, 0 );
329                 ber_memfree( nbase.bv_val );
330
331                 if( be == NULL ) {
332                         fprintf( stderr, "%s: slap_init no backend for \"%s\"\n",
333                                 progname, base.bv_val );
334                         exit( EXIT_FAILURE );
335                 }
336                 /* If the named base is a glue master, operate on the
337                  * entire context
338                  */
339                 if (SLAP_GLUE_INSTANCE(be)) {
340                         nosubordinates = 1;
341                 }
342
343         } else if ( dbnum == -1 ) {
344                 if ( nbackends <= 0 ) {
345                         fprintf( stderr, "No available databases\n" );
346                         exit( EXIT_FAILURE );
347                 }
348                 
349                 be = &backends[dbnum=0];
350                 /* If just doing the first by default and it is a
351                  * glue subordinate, find the master.
352                  */
353                 while (SLAP_GLUE_SUBORDINATE(be) || SLAP_MONITOR(be)) {
354                         if (SLAP_GLUE_SUBORDINATE(be)) {
355                                 nosubordinates = 1;
356                         }
357                         be++;
358                         dbnum++;
359                 }
360
361
362                 if ( dbnum >= nbackends ) {
363                         fprintf( stderr, "Available database(s) "
364                                         "do not allow %s\n", name );
365                         exit( EXIT_FAILURE );
366                 }
367                 
368                 if ( nosubordinates == 0 && dbnum > 0 ) {
369 #ifdef NEW_LOGGING
370                         LDAP_LOG( BACKEND, ERR, 
371 "The first database does not allow %s; using the first available one (%d)\n",
372                                 name, dbnum + 1, 0 );
373 #else
374                         Debug( LDAP_DEBUG_ANY,
375 "The first database does not allow %s; using the first available one (%d)\n",
376                                 name, dbnum + 1, 0 );
377 #endif
378                 }
379
380         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
381                 fprintf( stderr,
382                         "Database number selected via -n is out of range\n"
383                         "Must be in the range 1 to %d"
384                                 " (number of databases in the config file)\n",
385                         nbackends );
386                 exit( EXIT_FAILURE );
387
388         } else {
389                 be = &backends[dbnum];
390         }
391
392 #ifdef CSRIMALLOC
393         mal_leaktrace(1);
394 #endif
395
396         slap_startup( be );
397 }
398
399 void slap_tool_destroy( void )
400 {
401         slap_shutdown( be );
402         slap_destroy();
403 #ifdef SLAPD_MODULES
404         if ( slapMode == SLAP_SERVER_MODE ) {
405         /* always false. just pulls in necessary symbol references. */
406                 lutil_uuidstr(NULL, 0);
407         }
408         module_kill();
409 #endif
410         schema_destroy();
411 #ifdef HAVE_TLS
412         ldap_pvt_tls_destroy();
413 #endif
414         config_destroy();
415
416 #ifdef CSRIMALLOC
417         mal_dumpleaktrace( leakfile );
418 #endif
419 }