]> git.sur5r.net Git - openldap/blob - servers/slurpd/main.c
3d659b34dd6b5daea6a130171dd2a77787066b45
[openldap] / servers / slurpd / main.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Copyright (c) 1996 Regents of the University of Michigan.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms are permitted
11  * provided that this notice is preserved and that due credit is given
12  * to the University of Michigan at Ann Arbor. The name of the University
13  * may not be used to endorse or promote products derived from this
14  * software without specific prior written permission. This software
15  * is provided ``as is'' without express or implied warranty.
16  */
17
18
19 /* 
20  * main.c - main routine for slurpd.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26 #include <sys/stat.h>
27 #include <ac/stdlib.h>
28 #include <ac/unistd.h>
29
30 #include "slurp.h"
31 #include "globals.h"
32 #include "lutil.h"
33
34 #include <ldap_pvt.h>
35
36 #ifdef HAVE_NT_SERVICE_MANAGER
37 #define MAIN_RETURN(x)  return
38 #define SERVICE_EXIT( e, n )    do { \
39         if ( is_NT_Service ) { \
40                 lutil_ServiceStatus.dwWin32ExitCode = (e); \
41                 lutil_ServiceStatus.dwServiceSpecificExitCode = (n); \
42         } \
43 } while ( 0 )
44 #else
45 #define SERVICE_EXIT( e, n )
46 #define MAIN_RETURN(x)  return(x)
47 #endif
48
49 #ifdef HAVE_NT_SERVICE_MANAGER
50 void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
51 #else
52 int main( int argc, char **argv )
53 #endif
54 {
55 #ifdef NO_THREADS
56     /* Haven't yet written the non-threaded version */
57     fputs( "slurpd currently requires threads support\n", stderr );
58     return( 1 );
59 #else
60
61     int                 i, rc = 0;
62
63     /* initialize thread package */
64     ldap_pvt_thread_initialize();
65
66     /* 
67      * Create and initialize globals.  init_globals() also initializes
68      * the main replication queue.
69      */
70     if (( sglob = init_globals()) == NULL ) {
71         fprintf( stderr, "Out of memory initializing globals\n" );
72         SERVICE_EXIT( ERROR_NOT_ENOUGH_MEMORY, 0 );
73         rc = 1;
74         goto stop;
75     }
76
77 #ifdef HAVE_NT_SERVICE_MANAGER
78         {
79                 int *i;
80                 char *newConfigFile;
81                 char *regService = NULL;
82
83                 if ( is_NT_Service ) {
84                         sglob->serverName = argv[0];
85                         lutil_CommenceStartupProcessing( sglob->serverName, slurp_set_shutdown );
86                         if ( strcmp(sglob->serverName, SERVICE_NAME) )
87                             regService = sglob->serverName;
88                 }
89
90                 i = (int*)lutil_getRegParam( regService, "DebugLevel" );
91                 if ( i != NULL ) 
92                 {
93                         ldap_debug = *i;
94 #ifdef NEW_LOGGING
95                         lutil_log_initialize( argc, argv );
96                         LDAP_LOG( SLURPD, INFO, 
97                                 "main: new debug level from registry is: %d\n", 
98                                 ldap_debug, 0, 0 );
99 #else
100                         Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", ldap_debug, 0, 0 );
101 #endif
102                 }
103
104                 newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
105                 if ( newConfigFile != NULL ) 
106                 {
107                         sglob->slapd_configfile = newConfigFile;
108 #ifdef NEW_LOGGING
109                         LDAP_LOG( SLURPD, INFO, 
110                                 "main: new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 );
111 #else
112                         Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", sglob->slapd_configfile, 0, 0 );
113 #endif
114
115                 }
116         }
117 #endif
118
119     /*
120      * Process command-line args and fill in globals.
121      */
122     if ( doargs( argc, argv, sglob ) < 0 ) {
123         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
124         rc = 1;
125         goto stop;
126     }
127
128     /*
129      * Read slapd config file and initialize Re (per-replica) structs.
130      */
131     if ( slurpd_read_config( sglob->slapd_configfile ) < 0 ) {
132         fprintf( stderr,
133                 "Errors encountered while processing config file \"%s\"\n",
134                 sglob->slapd_configfile );
135         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
136         rc = 1;
137         goto stop;
138     }
139
140 #ifdef HAVE_TLS
141         if( ldap_pvt_tls_init() || ldap_pvt_tls_init_def_ctx() ) {
142                 fprintf( stderr, "TLS Initialization failed.\n" );
143                 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
144                 rc = 1;
145                 goto stop;
146         }
147 #endif
148
149     /* 
150      * Make sure our directory exists
151      */
152     if ( mkdir(sglob->slurpd_rdir, 0755) == -1 && errno != EEXIST) {
153         perror(sglob->slurpd_rdir);
154         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
155         rc = 1;
156         goto stop;
157     }
158
159     /*
160      * Get any saved state information off the disk.
161      */
162     if ( sglob->st->st_read( sglob->st )) {
163         fprintf( stderr, "Malformed slurpd status file \"%s\"\n",
164                 sglob->slurpd_status_file, 0, 0 );
165         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 17 );
166         rc = 1;
167         goto stop;
168     }
169
170     /*
171      * All readonly data should now be initialized. 
172      * Check for any fatal error conditions before we get started
173      */
174      if ( sanity() < 0 ) {
175         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
176         rc = 1;
177         goto stop;
178     }
179
180
181     /*
182      * Detach from the controlling terminal
183      * unless the -d flag is given or in one-shot mode.
184      */
185 #ifndef HAVE_WINSOCK
186         if ( ! (sglob->no_detach || sglob->one_shot_mode) ) {
187                 lutil_detach( 0, 0 );
188         }
189 #endif
190
191         if ( slurpd_pid_file != NULL ) {
192                 FILE *fp = fopen( slurpd_pid_file, "w" );
193
194                 if( fp != NULL ) {
195                         fprintf( fp, "%d\n", (int) getpid() );
196                         fclose( fp );
197
198                 } else {
199                 free(slurpd_pid_file);
200                 slurpd_pid_file = NULL;
201                 }
202         }
203
204         if ( slurpd_args_file != NULL ) {
205                 FILE *fp = fopen( slurpd_args_file, "w" );
206
207                 if( fp != NULL ) {
208                         for ( i = 0; i < argc; i++ ) {
209                                 fprintf( fp, "%s ", argv[i] );
210                         }
211                         fprintf( fp, "\n" );
212                         fclose( fp );
213                 } else {
214                         free(slurpd_args_file);
215                         slurpd_args_file = NULL;
216                 }
217         }
218
219     if ( (rc = lutil_pair( sglob->wake_sds )) < 0 ) {
220         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
221         rc = 1;
222         goto stop;
223     }
224         
225 #ifdef HAVE_NT_EVENT_LOG
226         if (is_NT_Service) lutil_LogStartedEvent( sglob->serverName, ldap_debug, sglob->slapd_configfile, "n/a" );
227 #endif
228
229     /*
230      * Start the main file manager thread (in fm.c).
231      */
232     if ( ldap_pvt_thread_create( &(sglob->fm_tid),
233                 0, fm, (void *) NULL ) != 0 )
234         {
235 #ifdef NEW_LOGGING
236         LDAP_LOG ( SLURPD, ERR,
237                 "main: file manager ldap_pvt_thread_create failed\n" , 0, 0, 0 );
238 #else
239         Debug( LDAP_DEBUG_ANY, "file manager ldap_pvt_thread_create failed\n",
240                 0, 0, 0 );
241 #endif
242         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
243         rc = 1;
244         goto stop;
245
246     }
247
248     /*
249      * wait for fm to finish if in oneshot mode
250      */
251     if ( sglob->one_shot_mode ) {
252         ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
253     }
254
255     /*
256      * Start threads - one thread for each replica
257      */
258     for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
259         start_replica_thread( sglob->replicas[ i ]);
260     }
261
262 #ifdef HAVE_NT_SERVICE_MANAGER
263     if ( started_event ) ldap_pvt_thread_cond_signal( &started_event );
264 #endif
265
266     /*
267      * Wait for the fm thread to finish.
268      */
269     if ( !sglob->one_shot_mode ) {
270         ldap_pvt_thread_join( sglob->fm_tid, (void *) NULL );
271     }
272
273     /*
274      * Wait for the replica threads to finish.
275      */
276     for ( i = 0; sglob->replicas[ i ] != NULL; i++ ) {
277         ldap_pvt_thread_join( sglob->replicas[ i ]->ri_tid, (void *) NULL );
278     }
279
280 stop:
281 #ifdef HAVE_NT_SERVICE_MANAGER
282         if (is_NT_Service) {
283                 ldap_pvt_thread_cond_destroy( &started_event );
284                 lutil_LogStoppedEvent( sglob->serverName );
285                 lutil_ReportShutdownComplete();
286         }
287 #endif
288     /* destroy the thread package */
289     ldap_pvt_thread_destroy();
290
291 #ifdef HAVE_TLS
292     ldap_pvt_tls_destroy();
293 #endif
294
295 #ifdef NEW_LOGGING
296         LDAP_LOG ( SLURPD, RESULTS, "main: slurpd terminated\n", 0, 0, 0 );
297 #else
298     Debug( LDAP_DEBUG_ANY, "slurpd: terminated.\n", 0, 0, 0 );
299 #endif
300
301     if ( slurpd_pid_file != NULL ) {
302         unlink( slurpd_pid_file );
303     }
304     if ( slurpd_args_file != NULL ) {
305         unlink( slurpd_args_file );
306     }
307
308
309         MAIN_RETURN(rc);
310 #endif /* !NO_THREADS */
311 }