]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldif2ldbm-bdb2.c
Very crude LDIF changes:
[openldap] / servers / slapd / tools / ldif2ldbm-bdb2.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 "ldap_defaults.h"
14 #include "../slap.h"
15 #include "../back-bdb2/back-bdb2.h"
16 #include "ldif.h"
17
18 #define INDEXCMD                "ldif2index-bdb2"
19 #define ID2ENTRYCMD             "ldif2id2entry-bdb2"
20 #define ID2CHILDRENCMD          "ldif2id2children-bdb2"
21 #define MAXARGS                 100
22
23 static void fork_child( char *prog, char *args[] );
24 static void     wait4kids( int nkidval );
25
26 static char     *tailorfile;
27 static char     *inputfile;
28 static int      maxkids = 1;
29 static int      nkids;
30
31 static void
32 usage( char *name )
33 {
34         fprintf( stderr, "usage: %s -i inputfile [-d debuglevel] [-f configfile] [-j #jobs] [-n databasenumber] [-s sbindir]\n", name );
35         exit( 1 );
36 }
37
38 int
39 main( int argc, char **argv )
40 {
41         int             i, stop;
42         char            *linep, *buf, *sbindir;
43         char            *args[MAXARGS];
44         char            buf2[20], buf3[20];
45         char            line[BUFSIZ];
46         char            cmd[MAXPATHLEN];
47         int             lineno, elineno;
48         int             lmax, lcur;
49         int             dbnum;
50         ID              id;
51         int             rc;
52         Backend         *be = NULL;
53         struct ldbminfo *li;
54         struct berval   bv;
55         struct berval   *vals[2];
56         Avlnode         *avltypes = NULL;
57
58         sbindir = LDAP_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         rc = slap_init(SLAP_TOOL_MODE, "ldif2ldbm");
107         if (rc != 0 ) {
108                 fprintf( stderr, "ldif2ldbm: slap_init failed!\n");
109                 exit(1);
110         }
111
112         read_config( tailorfile );
113
114         if ( dbnum == -1 ) {
115                 for ( dbnum = 0; dbnum < nbackends; dbnum++ ) {
116                         if ( strcasecmp( backends[dbnum].be_type, "bdb2" )
117                             == 0 ) {
118                                 break;
119                         }
120                 }
121                 if ( dbnum == nbackends ) {
122                         fprintf( stderr, "No bdb2 database found in config file\n" );
123                         exit( 1 );
124                 }
125         } else if ( dbnum < 0 || dbnum > (nbackends-1) ) {
126                 fprintf( stderr, "Database number selected via -n is out of range\n" );
127                 fprintf( stderr, "Must be in the range 1 to %d (number of databases in the config file)\n", nbackends );
128                 exit( 1 );
129         } else if ( strcasecmp( backends[dbnum].be_type, "bdb2" ) != 0 ) {
130                 fprintf( stderr, "Database number %d selected via -n is not an bdb2 database\n", dbnum );
131                 exit( 1 );
132         }
133
134         slap_startup(dbnum);
135
136         be = &backends[dbnum];
137
138         /* disable write sync'ing */
139         li = (struct ldbminfo *) be->be_private;
140         li->li_dbcachewsync = 0;
141
142         /*
143          * generate the id2entry index
144          */
145
146         i = 0;
147         sprintf( cmd, "%s/%s", sbindir, ID2ENTRYCMD );
148         args[i++] = cmd;
149         args[i++] = "-i";
150         args[i++] = inputfile;
151         args[i++] = "-f";
152         args[i++] = tailorfile;
153         args[i++] = "-n";
154         sprintf( buf2, "%d", dbnum+1 );
155         args[i++] = buf2;
156         if ( ldap_debug ) {
157                 sprintf( buf3, "%d", ldap_debug );
158                 args[i++] = "-d";
159                 args[i++] = buf3;
160         }
161         args[i++] = NULL;
162         fork_child( cmd, args );
163
164         /*
165          * generate the dn2id and id2children indexes
166          */
167
168         i = 0;
169         sprintf( cmd, "%s/%s", sbindir, ID2CHILDRENCMD );
170         args[i++] = cmd;
171         args[i++] = "-i";
172         args[i++] = inputfile;
173         args[i++] = "-f";
174         args[i++] = tailorfile;
175         args[i++] = "-n";
176         sprintf( buf2, "%d", dbnum+1 );
177         args[i++] = buf2;
178         if ( ldap_debug ) {
179                 sprintf( buf3, "%d", ldap_debug );
180                 args[i++] = "-d";
181                 args[i++] = buf3;
182         }
183         args[i++] = NULL;
184         fork_child( cmd, args );
185
186         /*
187          * generate the attribute indexes
188          */
189
190         i = 0;
191         sprintf( cmd, "%s/%s", sbindir, INDEXCMD );
192         args[i++] = cmd;
193         args[i++] = "-i";
194         args[i++] = inputfile;
195         args[i++] = "-f";
196         args[i++] = tailorfile;
197         args[i++] = "-n";
198         sprintf( buf2, "%d", dbnum+1 );
199         args[i++] = buf2;
200         if ( ldap_debug ) {
201                 sprintf( buf3, "%d", ldap_debug );
202                 args[i++] = "-d";
203                 args[i++] = buf3;
204         }
205         args[i++] = NULL;               /* will hold the attribute name */
206         args[i++] = NULL;
207
208         id = 0;
209         stop = 0;
210         buf = NULL;
211         lineno = 0;
212         lcur = lmax = 0;
213         vals[0] = &bv;
214         vals[1] = NULL;
215         while ( ! stop ) {
216                 char            *type, *val, *s;
217                 int             vlen, indexmask, syntaxmask;
218
219                 if ( fgets( line, sizeof(line), stdin ) != NULL ) {
220                         int     len;
221
222                         lineno++;
223                         len = strlen( line );
224                         while ( lcur + len + 1 > lmax ) {
225                                 lmax += BUFSIZ;
226                                 buf = (char *) ch_realloc( buf, lmax );
227                         }
228                         strcpy( buf + lcur, line );
229                         lcur += len;
230                 } else {
231                         stop = 1;
232                 }
233                 if ( line[0] == '\n' || stop && buf && *buf ) {
234                         id++;
235                         s = buf;
236                         elineno = 0;
237                         while ( (linep = ldif_getline( &s )) != NULL ) {
238                                 elineno++;
239                                 if ( ldif_parse_line( linep, &type, &val, &vlen )
240                                     != 0 ) {
241                                         Debug( LDAP_DEBUG_PARSE,
242                             "bad line %d in entry ending at line %d ignored\n",
243                                             elineno, lineno, 0 );
244                                         continue;
245                                 }
246
247                                 if ( !isascii( *type ) || isdigit( *type ) )
248                                         continue;
249
250                                 type = strdup( type );
251                                 if ( avl_insert( &avltypes, type, strcasecmp,
252                                     avl_dup_error ) != 0 ) {
253                                         free( type );
254                                 } else {
255                                         bdb2i_attr_masks( be->be_private, type,
256                                             &indexmask, &syntaxmask );
257                                         if ( indexmask ) {
258                                                 args[i - 2] = type;
259                                                 fork_child( cmd, args );
260                                         }
261                                 }
262                         }
263                         *buf = '\0';
264                         lcur = 0;
265                 }
266         }
267
268         slap_shutdown(dbnum);
269
270         wait4kids( -1 );
271
272         slap_destroy();
273
274         exit( 0 );
275 }
276
277 static void
278 fork_child( char *prog, char *args[] )
279 {
280         int     pid;
281
282         wait4kids( maxkids );
283
284         switch ( pid = fork() ) {
285         case 0:         /* child */
286                 execvp( prog, args );
287                 fprintf( stderr, "%s: ", prog );
288                 perror( "execv" );
289                 exit( -1 );
290                 break;
291
292         case -1:        /* trouble */
293                 fprintf( stderr, "Could not fork to run %s\n", prog );
294                 perror( "fork" );
295                 break;
296
297         default:        /* parent */
298                 nkids++;
299                 break;
300         }
301 }
302
303 static void
304 wait4kids( int nkidval )
305 {
306         int             status;
307         unsigned char   *p;
308
309         while ( nkids >= nkidval ) {
310                 wait( &status );
311                 p = (unsigned char *) &status;
312                 if ( p[sizeof(int) - 1] == 0177 ) {
313                         fprintf( stderr,
314                             "stopping: child stopped with signal %d\n",
315                             p[sizeof(int) - 2] );
316                 } else if ( p[sizeof(int) - 1] != 0 ) {
317                         fprintf( stderr, 
318                             "stopping: child terminated with signal %d\n",
319                             p[sizeof(int) - 1] );
320                         exit( p[sizeof(int) - 1] );
321                 } else if ( p[sizeof(int) - 2] != 0 ) {
322                         fprintf( stderr, 
323                             "stopping: child exited with status %d\n",
324                             p[sizeof(int) - 2] );
325                         exit( p[sizeof(int) - 2] );
326                 } else {
327                         nkids--;
328                 }
329         }
330 }