]> git.sur5r.net Git - openldap/blob - servers/slapd/main.c
Rework ac/socket.h for HAVE_WINSOCK:
[openldap] / servers / slapd / main.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/signal.h>
6 #include <ac/socket.h>
7 #include <ac/string.h>
8 #include <ac/time.h>
9 #include <ac/unistd.h>
10 #include <ac/wait.h>
11 #include <ac/signal.h>
12 #include <ac/errno.h>
13
14 #include "ldapconfig.h"
15 #include "slap.h"
16 #include "lutil.h"                      /* Get lutil_detach() */
17
18 #if defined(SIGCHLD) || defined(SIGCLD)
19 static RETSIGTYPE wait4child( int sig );
20 #endif
21
22 /*
23  * when more than one slapd is running on one machine, each one might have
24  * it's own LOCAL for syslogging and must have its own pid/args files
25  */
26
27 #ifdef LOG_LOCAL4
28
29 #define DEFAULT_SYSLOG_USER  LOG_LOCAL4
30
31 typedef struct _str2intDispatch {
32         char    *stringVal;
33         int      abbr;
34         int      intVal;
35 } STRDISP, *STRDISP_P;
36
37
38 /* table to compute syslog-options to integer */
39 static STRDISP  syslog_types[] = {
40     { "LOCAL0",         6, LOG_LOCAL0 },
41     { "LOCAL1",         6, LOG_LOCAL1 },
42     { "LOCAL2",         6, LOG_LOCAL2 },
43     { "LOCAL3",         6, LOG_LOCAL3 },
44     { "LOCAL4",         6, LOG_LOCAL4 },
45     { "LOCAL5",         6, LOG_LOCAL5 },
46     { "LOCAL6",         6, LOG_LOCAL6 },
47     { "LOCAL7",         6, LOG_LOCAL7 },
48     { NULL }
49 };
50
51 static int   cnvt_str2int( char *, STRDISP_P, int );
52
53 #endif  /* LOG_LOCAL4 */
54
55
56 static void
57 usage( char *name )
58 {
59         fprintf( stderr, "usage: %s [-d ?|debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]", name );
60 #ifdef LOG_LOCAL4
61     fprintf( stderr, " [-l sysloguser]" );
62 #endif
63     fprintf( stderr, "\n" );
64 }
65
66 time_t starttime;
67
68 int
69 main( int argc, char **argv )
70 {
71         int             i;
72         int             inetd = 0;
73         int             status, rc;
74         struct sockaddr_in      bind_addr, *slapd_addr;
75         int             udp;
76 #ifdef LOG_LOCAL4
77     int     syslogUser = DEFAULT_SYSLOG_USER;
78 #endif
79         char            *configfile;
80         char        *serverName;
81         int         serverMode = SLAP_SERVER_MODE;
82
83         configfile = SLAPD_DEFAULT_CONFIGFILE;
84
85         (void) memset( (void*) &bind_addr, '\0', sizeof(bind_addr));
86         bind_addr.sin_family = AF_INET;
87         bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
88         bind_addr.sin_port = htons(LDAP_PORT);
89
90         g_argc = argc;
91         g_argv = argv;
92
93 #ifdef SLAPD_BDB2
94         while ( (i = getopt( argc, argv, "d:f:ia:p:s:ut" )) != EOF ) {
95 #else
96         while ( (i = getopt( argc, argv, "d:f:ia:p:s:u" )) != EOF ) {
97 #endif
98                 switch ( i ) {
99                 case 'a':       /* bind address */
100                         if(!inet_aton(optarg, &bind_addr.sin_addr)) {
101                                 fprintf(stderr, "invalid address (%s) for -a option", optarg);
102                         }
103             break;
104
105 #ifdef LDAP_DEBUG
106                 case 'd':       /* turn on debugging */
107                         if ( optarg[0] == '?' ) {
108                                 printf( "Debug levels:\n" );
109                                 printf( "\tLDAP_DEBUG_TRACE\t%d\n",
110                                     LDAP_DEBUG_TRACE );
111                                 printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
112                                     LDAP_DEBUG_PACKETS );
113                                 printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
114                                     LDAP_DEBUG_ARGS );
115                                 printf( "\tLDAP_DEBUG_CONNS\t%d\n",
116                                     LDAP_DEBUG_CONNS );
117                                 printf( "\tLDAP_DEBUG_BER\t\t%d\n",
118                                     LDAP_DEBUG_BER );
119                                 printf( "\tLDAP_DEBUG_FILTER\t%d\n",
120                                     LDAP_DEBUG_FILTER );
121                                 printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
122                                     LDAP_DEBUG_CONFIG );
123                                 printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
124                                     LDAP_DEBUG_ACL );
125                                 printf( "\tLDAP_DEBUG_STATS\t%d\n",
126                                     LDAP_DEBUG_STATS );
127                                 printf( "\tLDAP_DEBUG_STATS2\t%d\n",
128                                     LDAP_DEBUG_STATS2 );
129                                 printf( "\tLDAP_DEBUG_SHELL\t%d\n",
130                                     LDAP_DEBUG_SHELL );
131                                 printf( "\tLDAP_DEBUG_PARSE\t%d\n",
132                                     LDAP_DEBUG_PARSE );
133                                 printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
134                                     LDAP_DEBUG_ANY );
135                                 exit( 0 );
136                         } else {
137                                 slap_debug |= atoi( optarg );
138                         }
139                         break;
140 #else
141                 case 'd':       /* turn on debugging */
142                         fprintf( stderr,
143                             "must compile with LDAP_DEBUG for debugging\n" );
144                         break;
145 #endif
146
147                 case 'f':       /* read config file */
148                         configfile = ch_strdup( optarg );
149                         break;
150
151                 case 'i':       /* run from inetd */
152                         inetd = 1;
153                         break;
154
155                 case 'p': {     /* port on which to listen */
156                                 int port = atoi( optarg );
157                                 if(! port ) {
158                                         fprintf(stderr, "-p %s must be numeric\n", optarg);
159                                 } else {
160                                         bind_addr.sin_port = htons(port);
161                                 }
162                         } break;
163
164                 case 's':       /* set syslog level */
165                         ldap_syslog = atoi( optarg );
166                         break;
167
168 #ifdef LOG_LOCAL4
169                 case 'l':       /* set syslog local user */
170                         syslogUser = cnvt_str2int( optarg, syslog_types,
171                                            DEFAULT_SYSLOG_USER );
172                         break;
173 #endif
174
175                 case 'u':       /* do udp */
176                         udp = 1;
177                         break;
178
179 #ifdef SLAPD_BDB2
180                 case 't':  /* timed server */
181                         serverMode = SLAP_TIMEDSERVER_MODE;
182                         break;
183 #endif
184
185                 default:
186                         usage( argv[0] );
187                         exit( 1 );
188                 }
189         }
190
191         lber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
192         ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
193         ldif_debug = slap_debug;
194
195         Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
196
197         if ( (serverName = strrchr( argv[0], '/' )) == NULL ) {
198                 serverName = ch_strdup( argv[0] );
199         } else {
200                 serverName = ch_strdup( serverName + 1 );
201         }
202
203 #ifdef LOG_LOCAL4
204         openlog( serverName, OPENLOG_OPTIONS, syslogUser );
205 #else
206         openlog( serverName, OPENLOG_OPTIONS );
207 #endif
208
209         if ( slap_init( serverMode, serverName ) != 0 ) {
210                 rc = 1;
211                 goto destroy;
212         }
213
214         if ( read_config( configfile ) != 0 ) {
215                 rc = 1;
216                 goto destroy;
217         }
218
219         (void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
220         (void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
221 #ifdef SIGPIPE
222         (void) SIGNAL( SIGPIPE, SIG_IGN );
223 #endif
224 #ifdef SIGHUP
225         (void) SIGNAL( SIGHUP, slap_set_shutdown );
226 #endif
227         (void) SIGNAL( SIGINT, slap_set_shutdown );
228         (void) SIGNAL( SIGTERM, slap_set_shutdown );
229 #ifdef SIGCHLD
230         (void) SIGNAL( SIGCHLD, wait4child );
231 #elif defined(SIGCLD)
232         (void) SIGNAL( SIGCLD, wait4child );
233 #endif
234
235         if(!inetd) {
236 #ifdef LDAP_DEBUG
237                 lutil_detach( ldap_debug, 0 );
238 #else
239                 lutil_detach( 0, 0 );
240 #endif
241         }
242
243         if ( slap_startup(-1)  != 0 ) {
244                 rc = 1;
245                 goto shutdown;
246         }
247
248         if(!inetd) {
249                 FILE *fp;
250
251                 slapd_addr = &bind_addr;
252
253                 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
254
255                 if (( slapd_pid_file != NULL ) &&
256                         (( fp = fopen( slapd_pid_file, "w" )) != NULL ))
257                 {
258                         fprintf( fp, "%d\n", (int) getpid() );
259                         fclose( fp );
260                 }
261
262                 if (( slapd_args_file != NULL ) &&
263                         (( fp = fopen( slapd_args_file, "w" )) != NULL ))
264                 {
265                         for ( i = 0; i < g_argc; i++ ) {
266                                 fprintf( fp, "%s ", g_argv[i] );
267                         }
268                         fprintf( fp, "\n" );
269                         fclose( fp );
270                 }
271
272         } else {
273                 slapd_addr = NULL;
274         }
275
276         time( &starttime );
277
278         rc = slapd_daemon( slapd_addr );
279
280 shutdown:
281         /* remember an error during shutdown */
282         rc |= slap_shutdown(-1);
283 destroy:
284         /* remember an error during destroy */
285         rc |= slap_destroy();
286
287         Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
288
289         return rc;
290 }
291
292
293 #if defined(SIGCHLD) || defined(SIGCLD)
294
295 /*
296  *  Catch and discard terminated child processes, to avoid zombies.
297  */
298
299 static RETSIGTYPE
300 wait4child( int sig )
301 {
302     int save_errno = errno;
303     errno = 0;
304     /*
305      * ### The wait3 vs. waitpid choice needs improvement.
306      * ### There are apparently systems where waitpid(-1, ...) fails, and
307      * ### others where waitpid should preferred over wait3 for some reason.
308      * ### Now wait3 is only here for reference, configure does not detect it.
309      */
310 #if defined(HAVE_WAITPID) && defined(WNOHANG)
311     while ( waitpid( (pid_t)-1, NULL, WNOHANG ) >= 0 || errno == EINTR )
312         ;       /* NULL */
313 #elif defined(HAVE_WAIT3) && defined(WNOHANG)
314     while ( wait3( NULL, WNOHANG, NULL ) >= 0 || errno == EINTR )
315         ;       /* NULL */
316 #else
317     (void) wait( NULL );
318 #endif
319     (void) signal( sig, wait4child );
320     errno = save_errno;
321 }
322
323 #endif /* SIGCHLD || SIGCLD */
324
325
326 #ifdef LOG_LOCAL4
327
328 /*
329  *  Convert a string to an integer by means of a dispatcher table
330  *  if the string is not in the table return the default
331  */
332
333 static int
334 cnvt_str2int( char *stringVal, STRDISP_P dispatcher, int defaultVal )
335 {
336     int        retVal = defaultVal;
337     STRDISP_P  disp;
338
339     for (disp = dispatcher; disp->stringVal; disp++) {
340
341         if (!strncasecmp (stringVal, disp->stringVal, disp->abbr)) {
342
343             retVal = disp->intVal;
344             break;
345
346         }
347     }
348
349     return (retVal);
350
351 } /* cnvt_str2int */
352
353 #endif  /* LOG_LOCAL4 */