]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldif2ldbm.c
s/<stdlib.h>/<ac/stdlib.h>/
[openldap] / servers / slapd / tools / ldif2ldbm.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/string.h>
6 #include <ac/ctype.h>
7 #include <ac/socket.h>
8 #include <ac/unistd.h>
9 #include <ac/wait.h>
10
11 #ifdef HAVE_SYS_PARAM_H
12 #include <sys/param.h>
13 #endif
14
15 #include "ldapconfig.h"
16 #include "../slap.h"
17 #include "../back-ldbm/back-ldbm.h"
18 #include "ldif.h"
19
20 #define INDEXCMD                "ldif2index" EXEEXT
21 #define ID2ENTRYCMD             "ldif2id2entry" EXEEXT
22 #define ID2CHILDRENCMD          "ldif2id2children" EXEEXT
23
24 #define MAXARGS                 100
25
26 static void fork_child( char *prog, char *args[] );
27 static void     wait4kids( int nkidval );
28
29 static char     *tailorfile;
30 static char     *inputfile;
31 static int      maxkids = 1;
32 static int      nkids;
33
34 static void
35 usage( char *name )
36 {
37         fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-j #jobs] [-n databasenumber] [-s sbindir]\n", name );
38     exit( 1 );
39 }
40
41 int
42 main( int argc, char **argv )
43 {
44         int             i, stop;
45         char            *linep, *buf, *sbindir;
46         char            *args[MAXARGS];
47         char            buf2[20], buf3[20];
48         char            line[BUFSIZ];
49         char            cmd[MAXPATHLEN];
50         int             lineno, elineno;
51         int             lmax, lcur;
52         int             dbnum;
53         ID              id;
54         int             rc;
55     int     cmdkids = 1;
56         Backend         *be = NULL;
57         struct ldbminfo *li;
58         struct berval   bv;
59         struct berval   *vals[2];
60         Avlnode         *avltypes = NULL;
61
62         ldbm_ignore_nextid_file = 1;
63
64         sbindir = DEFAULT_SBINDIR;
65         tailorfile = SLAPD_DEFAULT_CONFIGFILE;
66         dbnum = -1;
67         while ( (i = getopt( argc, argv, "d:e:s:f:i:j:n:" )) != EOF ) {
68                 switch ( i ) {
69                 case 'd':       /* turn on debugging */
70                         ldap_debug = atoi( optarg );
71                         break;
72
73                 case 's':       /* alternate sbindir (index cmd location) */
74                 case 'e':       /* accept -e for backwards compatibility */
75                         sbindir = strdup( optarg );
76                         break;
77
78                 case 'f':       /* specify a tailor file */
79                         tailorfile = strdup( optarg );
80                         break;
81
82                 case 'i':       /* input file */
83                         inputfile = strdup( optarg );
84                         break;
85
86                 case 'j':       /* number of parallel index procs */
87                         cmdkids = atoi( optarg );
88                         break;
89
90                 case 'n':       /* which config file db to index */
91                         dbnum = atoi( optarg ) - 1;
92                         break;
93
94                 default:
95                         usage( argv[0] );
96                         break;
97                 }
98         }
99         if ( inputfile == NULL ) {
100                 usage( argv[0] );
101         } else {
102                 if ( freopen( inputfile, "r", stdin ) == NULL ) {
103                         perror( inputfile );
104                         exit( 1 );
105                 }
106         }
107
108         /*
109          * initialize stuff and figure out which backend we're dealing with
110          */
111
112         rc = slap_init(SLAP_TOOL_MODE, "ldif2ldbm");
113         if (rc != 0 ) {
114                 fprintf( stderr, "ldif2ldbm: slap_init failed!\n");
115                 exit(1);
116         }
117
118         read_config( tailorfile );
119
120         if ( dbnum == -1 ) {
121                 for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
122                         if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
123                             == 0 ) {
124                                 break;
125                         }
126                 }
127                 if ( dbnum == nbackends ) {
128                         fprintf( stderr, "No ldbm database found in config file\n" );
129                         exit( 1 );
130                 }
131         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
132                 fprintf( stderr, "Database number selected via -n is out of range\n" );
133                 fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
134                 exit( 1 );
135         } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
136                 fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
137                 exit( 1 );
138         }
139
140         slap_startup(dbnum);
141
142         be = &backends[dbnum];
143
144         /* disable write sync'ing */
145         li = (struct ldbminfo *) be->be_private;
146         li->li_dbcachewsync = 0;
147
148         /*
149          * generate the id2entry index
150          */
151
152         i = 0;
153         sprintf( cmd, "%s/%s", sbindir, ID2ENTRYCMD );
154         args[i++] = cmd;
155         args[i++] = "-i";
156         args[i++] = inputfile;
157         args[i++] = "-f";
158         args[i++] = tailorfile;
159         args[i++] = "-n";
160         sprintf( buf2, "%d", dbnum+1 );
161         args[i++] = buf2;
162         if ( ldap_debug ) {
163                 sprintf( buf3, "%d", ldap_debug );
164                 args[i++] = "-d";
165                 args[i++] = buf3;
166         }
167         args[i++] = NULL;
168         fork_child( cmd, args );
169
170         /*
171          * generate the dn2id and id2children indexes
172          */
173
174         i = 0;
175         sprintf( cmd, "%s/%s", sbindir, ID2CHILDRENCMD );
176         args[i++] = cmd;
177         args[i++] = "-i";
178         args[i++] = inputfile;
179         args[i++] = "-f";
180         args[i++] = tailorfile;
181         args[i++] = "-n";
182         sprintf( buf2, "%d", dbnum+1 );
183         args[i++] = buf2;
184         if ( ldap_debug ) {
185                 sprintf( buf3, "%d", ldap_debug );
186                 args[i++] = "-d";
187                 args[i++] = buf3;
188         }
189         args[i++] = NULL;
190         fork_child( cmd, args );
191
192     maxkids = cmdkids;
193
194         /*
195          * generate the attribute indexes
196          */
197
198         i = 0;
199         sprintf( cmd, "%s/%s", sbindir, INDEXCMD );
200         args[i++] = cmd;
201         args[i++] = "-i";
202         args[i++] = inputfile;
203         args[i++] = "-f";
204         args[i++] = tailorfile;
205         args[i++] = "-n";
206         sprintf( buf2, "%d", dbnum+1 );
207         args[i++] = buf2;
208         if ( ldap_debug ) {
209                 sprintf( buf3, "%d", ldap_debug );
210                 args[i++] = "-d";
211                 args[i++] = buf3;
212         }
213         args[i++] = NULL;               /* will hold the attribute name */
214         args[i++] = NULL;
215
216         id = 0;
217         stop = 0;
218         buf = NULL;
219         lineno = 0;
220         lcur = lmax = 0;
221         vals[0] = &bv;
222         vals[1] = NULL;
223         while ( ! stop ) {
224                 char            *type, *val, *s;
225                 int             vlen, indexmask, syntaxmask;
226
227                 if ( fgets( line, sizeof(line), stdin ) != NULL ) {
228                         int     len;
229
230                         lineno++;
231                         len = strlen( line );
232                         while ( lcur + len + 1 > lmax ) {
233                                 lmax += BUFSIZ;
234                                 buf = (char *) ch_realloc( buf, lmax );
235                         }
236                         strcpy( buf + lcur, line );
237                         lcur += len;
238                 } else {
239                         stop = 1;
240                 }
241                 if ( line[0] == '\n' || stop && buf && *buf ) {
242                         id++;
243                         s = buf;
244                         elineno = 0;
245                         while ( (linep = ldif_getline( &s )) != NULL ) {
246                                 elineno++;
247                                 if ( ldif_parse_line( linep, &type, &val, &vlen )
248                                     != 0 ) {
249                                         Debug( LDAP_DEBUG_PARSE,
250                             "bad line %d in entry ending at line %d ignored\n",
251                                             elineno, lineno, 0 );
252                                         continue;
253                                 }
254
255                                 if ( !isascii( *type ) || isdigit( *type ) )
256                                         continue;
257
258                                 type = strdup( type );
259                                 if ( avl_insert( &avltypes, type, (AVL_CMP) strcasecmp,
260                                     avl_dup_error ) != 0 ) {
261                                         free( type );
262                                 } else {
263                                         attr_masks( be->be_private, type,
264                                             &indexmask, &syntaxmask );
265                                         if ( indexmask ) {
266                                                 args[i - 2] = type;
267                                                 fork_child( cmd, args );
268                                         }
269                                 }
270                         }
271                         *buf = '\0';
272                         lcur = 0;
273                 }
274         }
275
276         wait4kids( -1 );
277
278         slap_shutdown(dbnum);
279
280         slap_destroy();
281
282         return( 0 );
283 }
284
285 #ifdef WIN32
286
287 static HANDLE processes[MAXIMUM_WAIT_OBJECTS];
288
289 static void
290 fork_child( char *prog, char *args[] )
291 {
292     PROCESS_INFORMATION proc_info;
293     PROCESS_INFORMATION *pinfo = &proc_info;
294     STARTUPINFO  start_info;
295     int i;
296     char cmdLine[2048];
297
298     wait4kids( maxkids );
299
300     i = 1;
301     memset( &start_info, 0, sizeof(STARTUPINFO) );
302     memset( cmdLine, 0, sizeof(cmdLine) );
303     strcpy( cmdLine, prog );
304     while ( args[i] != NULL )
305     {
306         strcat( cmdLine, " " );
307         strcat( cmdLine, args[i] );
308         i++;
309     }
310
311     if ( !CreateProcess( NULL, cmdLine, NULL, NULL,
312                          TRUE, CREATE_NEW_CONSOLE,
313                          NULL, NULL, &start_info, pinfo ) )
314     {
315         fprintf( stderr, "Could not create %s: ", prog );
316         perror( "CreateProcess" );
317         exit (-1);
318     }
319
320     processes[nkids] = proc_info.hProcess;
321     nkids++;
322
323 }
324
325 static void
326 wait4kids( int nkidval )
327 {
328     DWORD  wait_index;
329     while( nkids >= nkidval )
330     {
331         wait_index = WaitForMultipleObjects( nkids, processes, FALSE, INFINITE );
332         /*
333         *  processes[wait_index] completed.  Move any remaining indexes into its
334         *  place in the array so it stays filled.
335         */
336         if ( nkids > 1 )
337         {
338             memcpy ( &processes[wait_index], &processes[wait_index+1], sizeof(HANDLE)*(nkids-1) );
339             processes[nkids] = 0;
340         }
341         nkids--;
342     }
343 }
344
345 #else
346
347 static void
348 fork_child( char *prog, char *args[] )
349 {
350         int     pid;
351
352         wait4kids( maxkids );
353
354         switch ( pid = fork() ) {
355         case 0:         /* child */
356                 execvp( prog, args );
357                 fprintf( stderr, "%s: ", prog );
358                 perror( "execv" );
359                 exit( -1 );
360                 break;
361
362         case -1:        /* trouble */
363                 fprintf( stderr, "Could not fork to run %s\n", prog );
364                 perror( "fork" );
365                 break;
366
367         default:        /* parent */
368                 nkids++;
369                 break;
370         }
371 }
372
373 static void
374 wait4kids( int nkidval )
375 {
376         int             status;
377         unsigned char   *p;
378
379         while ( nkids >= nkidval ) {
380                 wait( &status );
381                 p = (unsigned char *) &status;
382                 if ( p[sizeof(int) - 1] == 0177 ) {
383                         fprintf( stderr,
384                             "stopping: child stopped with signal %d\n",
385                             p[sizeof(int) - 2] );
386                 } else if ( p[sizeof(int) - 1] != 0 ) {
387                         fprintf( stderr, 
388                             "stopping: child terminated with signal %d\n",
389                             p[sizeof(int) - 1] );
390                         exit( p[sizeof(int) - 1] );
391                 } else if ( p[sizeof(int) - 2] != 0 ) {
392                         fprintf( stderr, 
393                             "stopping: child exited with status %d\n",
394                             p[sizeof(int) - 2] );
395                         exit( p[sizeof(int) - 2] );
396                 } else {
397                         nkids--;
398                 }
399         }
400 }
401
402 #endif