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