]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldif2ldbm.c
Import minor trace output cleanup
[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 #include <sys/param.h>
12
13 #include "ldapconfig.h"
14 #include "../slap.h"
15 #include "../back-ldbm/back-ldbm.h"
16 #include "ldif.h"
17
18 #define INDEXCMD                "ldif2index"
19 #define ID2ENTRYCMD             "ldif2id2entry"
20 #define ID2CHILDRENCMD          "ldif2id2children"
21 #define MAXARGS                 100
22
23 static void fork_child( char *prog, char *args[] );
24 static void     wait4kids( int nkidval );
25
26 static char     *indexcmd;
27 static char     *tailorfile;
28 static char     *inputfile;
29 static int      maxkids = 1;
30 static int      nkids;
31
32 static void
33 usage( char *name )
34 {
35         fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-j #jobs] [-n databasenumber] [-s sbindir]\n", name );
36         exit( 1 );
37 }
38
39 int
40 main( int argc, char **argv )
41 {
42         int             i, stop, status;
43         char            *linep, *buf, *sbindir;
44         char            *args[MAXARGS];
45         char            buf2[20], buf3[20];
46         char            line[BUFSIZ];
47         char            cmd[MAXPATHLEN];
48         int             lineno, elineno;
49         int             lmax, lcur;
50         int             dbnum;
51         ID              id;
52         Backend         *be = NULL;
53         struct ldbminfo *li;
54         struct berval   bv;
55         struct berval   *vals[2];
56         Avlnode         *avltypes = NULL;
57
58         sbindir = DEFAULT_SBINDIR;
59         tailorfile = SLAPD_DEFAULT_CONFIGFILE;
60         dbnum = -1;
61         while ( (i = getopt( argc, argv, "d:e:s:f:i:j:n:" )) != EOF ) {
62                 switch ( i ) {
63                 case 'd':       /* turn on debugging */
64                         ldap_debug = atoi( optarg );
65                         break;
66
67                 case 's':       /* alternate sbindir (index cmd location) */
68                 case 'e':       /* accept -e for backwards compatibility */
69                         sbindir = strdup( optarg );
70                         break;
71
72                 case 'f':       /* specify a tailor file */
73                         tailorfile = strdup( optarg );
74                         break;
75
76                 case 'i':       /* input file */
77                         inputfile = strdup( optarg );
78                         break;
79
80                 case 'j':       /* number of parallel index procs */
81                         maxkids = atoi( optarg );
82                         break;
83
84                 case 'n':       /* which config file db to index */
85                         dbnum = atoi( optarg ) - 1;
86                         break;
87
88                 default:
89                         usage( argv[0] );
90                         break;
91                 }
92         }
93         if ( inputfile == NULL ) {
94                 usage( argv[0] );
95         } else {
96                 if ( freopen( inputfile, "r", stdin ) == NULL ) {
97                         perror( inputfile );
98                         exit( 1 );
99                 }
100         }
101
102         /*
103          * initialize stuff and figure out which backend we're dealing with
104          */
105
106         init();
107         read_config( tailorfile, &be, NULL );
108
109         if ( dbnum == -1 ) {
110                 for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
111                         if ( strcasecmp( backends[dbnum].be_type, "ldbm" )
112                             == 0 ) {
113                                 break;
114                         }
115                 }
116                 if ( dbnum == nbackends ) {
117                         fprintf( stderr, "No ldbm database found in config file\n" );
118                         exit( 1 );
119                 }
120         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
121                 fprintf( stderr, "Database number selected via -n is out of range\n" );
122                 fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
123                 exit( 1 );
124         } else if ( strcasecmp( backends[dbnum].be_type, "ldbm" ) != 0 ) {
125                 fprintf( stderr, "Database number %d selected via -n is not an ldbm database\n", dbnum );
126                 exit( 1 );
127         }
128         be = &backends[dbnum];
129
130         /* disable write sync'ing */
131         li = (struct ldbminfo *) be->be_private;
132         li->li_dbcachewsync = 0;
133
134         /*
135          * generate the id2entry index
136          */
137
138         i = 0;
139         sprintf( cmd, "%s/%s", sbindir, ID2ENTRYCMD );
140         args[i++] = cmd;
141         args[i++] = "-i";
142         args[i++] = inputfile;
143         args[i++] = "-f";
144         args[i++] = tailorfile;
145         args[i++] = "-n";
146         sprintf( buf2, "%d", dbnum+1 );
147         args[i++] = buf2;
148         if ( ldap_debug ) {
149                 sprintf( buf3, "%d", ldap_debug );
150                 args[i++] = "-d";
151                 args[i++] = buf3;
152         }
153         args[i++] = NULL;
154         fork_child( cmd, args );
155
156         /*
157          * generate the dn2id and id2children indexes
158          */
159
160         i = 0;
161         sprintf( cmd, "%s/%s", sbindir, ID2CHILDRENCMD );
162         args[i++] = cmd;
163         args[i++] = "-i";
164         args[i++] = inputfile;
165         args[i++] = "-f";
166         args[i++] = tailorfile;
167         args[i++] = "-n";
168         sprintf( buf2, "%d", dbnum+1 );
169         args[i++] = buf2;
170         if ( ldap_debug ) {
171                 sprintf( buf3, "%d", ldap_debug );
172                 args[i++] = "-d";
173                 args[i++] = buf3;
174         }
175         args[i++] = NULL;
176         fork_child( cmd, args );
177
178         /*
179          * generate the attribute indexes
180          */
181
182         i = 0;
183         sprintf( cmd, "%s/%s", sbindir, INDEXCMD );
184         args[i++] = cmd;
185         args[i++] = "-i";
186         args[i++] = inputfile;
187         args[i++] = "-f";
188         args[i++] = tailorfile;
189         args[i++] = "-n";
190         sprintf( buf2, "%d", dbnum+1 );
191         args[i++] = buf2;
192         if ( ldap_debug ) {
193                 sprintf( buf3, "%d", ldap_debug );
194                 args[i++] = "-d";
195                 args[i++] = buf3;
196         }
197         args[i++] = NULL;               /* will hold the attribute name */
198         args[i++] = NULL;
199
200         id = 0;
201         stop = 0;
202         buf = NULL;
203         lineno = 0;
204         lcur = lmax = 0;
205         vals[0] = &bv;
206         vals[1] = NULL;
207         while ( ! stop ) {
208                 char            *type, *val, *s;
209                 int             vlen, indexmask, syntaxmask;
210                 Datum           key, data;
211
212                 ldbm_datum_init( key );
213                 ldbm_datum_init( data );
214
215                 if ( fgets( line, sizeof(line), stdin ) != NULL ) {
216                         int     len;
217
218                         lineno++;
219                         len = strlen( line );
220                         while ( lcur + len + 1 > lmax ) {
221                                 lmax += BUFSIZ;
222                                 buf = (char *) ch_realloc( buf, lmax );
223                         }
224                         strcpy( buf + lcur, line );
225                         lcur += len;
226                 } else {
227                         stop = 1;
228                 }
229                 if ( line[0] == '\n' || stop && buf && *buf ) {
230                         id++;
231                         s = buf;
232                         elineno = 0;
233                         while ( (linep = str_getline( &s )) != NULL ) {
234                                 elineno++;
235                                 if ( str_parse_line( linep, &type, &val, &vlen )
236                                     != 0 ) {
237                                         Debug( LDAP_DEBUG_PARSE,
238                             "bad line %d in entry ending at line %d ignored\n",
239                                             elineno, lineno, 0 );
240                                         continue;
241                                 }
242
243                                 if ( !isascii( *type ) || isdigit( *type ) )
244                                         continue;
245
246                                 type = strdup( type );
247                                 if ( avl_insert( &avltypes, type, strcasecmp,
248                                     avl_dup_error ) != 0 ) {
249                                         free( type );
250                                 } else {
251                                         attr_masks( be->be_private, type,
252                                             &indexmask, &syntaxmask );
253                                         if ( indexmask ) {
254                                                 args[i - 2] = type;
255                                                 fork_child( cmd, args );
256                                         }
257                                 }
258                         }
259                         *buf = '\0';
260                         lcur = 0;
261                 }
262         }
263         (*be->be_close)( be );
264
265         wait4kids( -1 );
266
267         exit( 0 );
268 }
269
270 static void
271 fork_child( char *prog, char *args[] )
272 {
273         int     status, pid;
274
275         wait4kids( maxkids );
276
277         switch ( pid = fork() ) {
278         case 0:         /* child */
279                 execvp( prog, args );
280                 fprintf( stderr, "%s: ", prog );
281                 perror( "execv" );
282                 exit( -1 );
283                 break;
284
285         case -1:        /* trouble */
286                 fprintf( stderr, "Could not fork to run %s\n", prog );
287                 perror( "fork" );
288                 break;
289
290         default:        /* parent */
291                 nkids++;
292                 break;
293         }
294 }
295
296 static void
297 wait4kids( int nkidval )
298 {
299         int             status;
300         unsigned char   *p;
301
302         while ( nkids >= nkidval ) {
303                 wait( &status );
304                 p = (unsigned char *) &status;
305                 if ( p[sizeof(int) - 1] == 0177 ) {
306                         fprintf( stderr,
307                             "stopping: child stopped with signal %d\n",
308                             p[sizeof(int) - 2] );
309                 } else if ( p[sizeof(int) - 1] != 0 ) {
310                         fprintf( stderr, 
311                             "stopping: child terminated with signal %d\n",
312                             p[sizeof(int) - 1] );
313                         exit( p[sizeof(int) - 1] );
314                 } else if ( p[sizeof(int) - 2] != 0 ) {
315                         fprintf( stderr, 
316                             "stopping: child exited with status %d\n",
317                             p[sizeof(int) - 2] );
318                         exit( p[sizeof(int) - 2] );
319                 } else {
320                         nkids--;
321                 }
322         }
323 }