]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/slapcommon.c
7e8514f277f57b71cd4813b0aaa393496f6d76fb
[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                 mode |= SLAP_TOOL_READMAIN;
109                 break;
110
111         case SLAPCAT:
112                 options = "b:cd:f:l:n:s:v";
113                 mode |= SLAP_TOOL_READMAIN | SLAP_TOOL_READONLY;
114                 break;
115
116         default:
117                 fprintf( stderr, "%s: unknown tool mode (%d)\n",
118                          progname, tool );
119                 exit( EXIT_FAILURE );
120         }
121
122         ldiffile = NULL;
123         conffile = SLAPD_DEFAULT_CONFIGFILE;
124         dbnum = -1;
125         while ( (i = getopt( argc, argv, options )) != EOF ) {
126                 switch ( i ) {
127                 case 'b':
128                         base.bv_val = strdup( optarg );
129                         base.bv_len = strlen( base.bv_val );
130                         break;
131
132                 case 'c':       /* enable continue mode */
133                         continuemode++;
134                         break;
135
136                 case 'd':       /* turn on debugging */
137                         ldap_debug += atoi( optarg );
138                         break;
139
140                 case 'f':       /* specify a conf file */
141                         conffile = strdup( optarg );
142                         break;
143
144                 case 'l':       /* LDIF file */
145                         ldiffile = strdup( optarg );
146                         break;
147
148                 case 'n':       /* which config file db to index */
149                         dbnum = atoi( optarg ) - 1;
150                         break;
151
152                 case 's':       /* dump subtree */
153                         subtree = strdup( optarg );
154                         break;
155
156                 case 't':       /* turn on truncate */
157                         truncatemode++;
158                         mode |= SLAP_TRUNCATE_MODE;
159                         break;
160
161                 case 'u':       /* dry run */
162                         dryrun++;
163                         break;
164
165                 case 'v':       /* turn on verbose */
166                         verbose++;
167                         break;
168
169                 default:
170                         usage( tool );
171                         break;
172                 }
173         }
174
175         if ( ( argc != optind ) || (dbnum >= 0 && base.bv_val != NULL ) ) {
176                 usage( tool );
177         }
178
179         if ( ldiffile == NULL ) {
180                 ldiffp = tool == SLAPCAT ? stdout : stdin;
181
182         } else if( (ldiffp = fopen( ldiffile, tool == SLAPCAT ? "w" : "r" ))
183                 == NULL )
184         {
185                 perror( ldiffile );
186                 exit( EXIT_FAILURE );
187         }
188
189         /*
190          * initialize stuff and figure out which backend we're dealing with
191          */
192
193 #ifdef SLAPD_MODULES
194         if ( module_init() != 0 ) {
195                 fprintf( stderr, "%s: module_init failed!\n", progname );
196                 exit( EXIT_FAILURE );
197         }
198 #endif
199                 
200         rc = slap_init( mode, progname );
201
202         if ( rc != 0 ) {
203                 fprintf( stderr, "%s: slap_init failed!\n", progname );
204                 exit( EXIT_FAILURE );
205         }
206
207         rc = slap_schema_init();
208
209         if ( rc != 0 ) {
210                 fprintf( stderr, "%s: slap_schema_init failed!\n", progname );
211                 exit( EXIT_FAILURE );
212         }
213
214         rc = read_config( conffile, 0 );
215
216         if ( rc != 0 ) {
217                 fprintf( stderr, "%s: bad configuration file!\n", progname );
218                 exit( EXIT_FAILURE );
219         }
220
221         if ( !nbackends ) {
222                 fprintf( stderr, "No databases found in config file\n" );
223                 exit( EXIT_FAILURE );
224         }
225
226         rc = glue_sub_init();
227
228         if ( rc != 0 ) {
229                 fprintf( stderr, "Subordinate configuration error\n" );
230                 exit( EXIT_FAILURE );
231         }
232
233         rc = slap_schema_check();
234
235         if ( rc != 0 ) {
236                 fprintf( stderr, "%s: slap_schema_prep failed!\n", progname );
237                 exit( EXIT_FAILURE );
238         }
239
240         if( subtree ) {
241                 struct berval val;
242                 val.bv_val = subtree;
243                 val.bv_len = strlen( subtree );
244                 rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL );
245                 if( rc != LDAP_SUCCESS ) {
246                         fprintf( stderr, "Invalid subtree DN '%s'\n", optarg );
247                         exit( EXIT_FAILURE );
248                 }
249
250                 if( base.bv_val == NULL && dbnum == -1 )
251                         base = val;
252                 else
253                         free( subtree );
254         }
255
256         if( base.bv_val != NULL ) {
257                 struct berval nbase;
258
259                 rc = dnNormalize( 0, NULL, NULL, &base, &nbase, NULL );
260                 if( rc != LDAP_SUCCESS ) {
261                         fprintf( stderr, "%s: slap_init invalid suffix (\"%s\")\n",
262                                 progname, base.bv_val );
263                         exit( EXIT_FAILURE );
264                 }
265
266                 be = select_backend( &nbase, 0, 0 );
267                 ber_memfree( nbase.bv_val );
268
269                 if( be == NULL ) {
270                         fprintf( stderr, "%s: slap_init no backend for \"%s\"\n",
271                                 progname, base.bv_val );
272                         exit( EXIT_FAILURE );
273                 }
274                 /* If the named base is a glue master, operate on the
275                  * entire context
276                  */
277                 if (SLAP_GLUE_INSTANCE(be)) {
278                         nosubordinates = 1;
279                 }
280
281         } else if ( dbnum == -1 ) {
282                 if ( nbackends <= 0 ) {
283                         fprintf( stderr, "No available databases\n" );
284                         exit( EXIT_FAILURE );
285                 }
286                 
287                 be = &backends[dbnum=0];
288                 /* If just doing the first by default and it is a
289                  * glue subordinate, find the master.
290                  */
291                 while (SLAP_GLUE_SUBORDINATE(be) || SLAP_MONITOR(be)) {
292                         if (SLAP_GLUE_SUBORDINATE(be)) {
293                                 nosubordinates = 1;
294                         }
295                         be++;
296                         dbnum++;
297                 }
298
299
300                 if ( dbnum >= nbackends ) {
301                         fprintf( stderr, "Available database(s) "
302                                         "do not allow %s\n", name );
303                         exit( EXIT_FAILURE );
304                 }
305                 
306                 if ( nosubordinates == 0 && dbnum > 0 ) {
307 #ifdef NEW_LOGGING
308                         LDAP_LOG( BACKEND, ERR, 
309 "The first database does not allow %s; using the first available one (%d)\n",
310                                 name, dbnum + 1, 0 );
311 #else
312                         Debug( LDAP_DEBUG_ANY,
313 "The first database does not allow %s; using the first available one (%d)\n",
314                                 name, dbnum + 1, 0 );
315 #endif
316                 }
317
318         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
319                 fprintf( stderr,
320                         "Database number selected via -n is out of range\n"
321                         "Must be in the range 1 to %d"
322                                 " (number of databases in the config file)\n",
323                         nbackends );
324                 exit( EXIT_FAILURE );
325
326         } else {
327                 be = &backends[dbnum];
328         }
329
330 #ifdef CSRIMALLOC
331         mal_leaktrace(1);
332 #endif
333
334         slap_startup( be );
335 }
336
337 void slap_tool_destroy( void )
338 {
339         slap_shutdown( be );
340         slap_destroy();
341 #ifdef SLAPD_MODULES
342         if ( slapMode == SLAP_SERVER_MODE ) {
343         /* always false. just pulls in necessary symbol references. */
344                 lutil_uuidstr(NULL, 0);
345         }
346         module_kill();
347 #endif
348         schema_destroy();
349 #ifdef HAVE_TLS
350         ldap_pvt_tls_destroy();
351 #endif
352         config_destroy();
353
354 #ifdef CSRIMALLOC
355         mal_dumpleaktrace( leakfile );
356 #endif
357 }