]> git.sur5r.net Git - openldap/blob - servers/slapd/main.c
s/WIN32/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 #ifdef LDAP_SIGCHLD
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 #ifndef HAVE_MKVERSION
28 const char Versionstr[] =
29         OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
30 #endif
31
32 #ifdef LOG_LOCAL4
33
34 #define DEFAULT_SYSLOG_USER  LOG_LOCAL4
35
36 typedef struct _str2intDispatch {
37         char    *stringVal;
38         int      abbr;
39         int      intVal;
40 } STRDISP, *STRDISP_P;
41
42
43 /* table to compute syslog-options to integer */
44 static STRDISP  syslog_types[] = {
45     { "LOCAL0",         6, LOG_LOCAL0 },
46     { "LOCAL1",         6, LOG_LOCAL1 },
47     { "LOCAL2",         6, LOG_LOCAL2 },
48     { "LOCAL3",         6, LOG_LOCAL3 },
49     { "LOCAL4",         6, LOG_LOCAL4 },
50     { "LOCAL5",         6, LOG_LOCAL5 },
51     { "LOCAL6",         6, LOG_LOCAL6 },
52     { "LOCAL7",         6, LOG_LOCAL7 },
53     { NULL }
54 };
55
56 static int   cnvt_str2int( char *, STRDISP_P, int );
57
58 #endif  /* LOG_LOCAL4 */
59
60
61 static void
62 usage( char *name )
63 {
64         fprintf( stderr, "usage: %s [-d ?|debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]", name );
65     fprintf( stderr, "\n        [-a bind-address] [-i]" );
66 #if LDAP_CONNECTIONLESS
67         fprintf( stderr, " [-c]" );
68 #endif
69 #ifdef SLAPD_BDB2
70     fprintf( stderr, " [-t]" );
71 #endif
72 #ifdef LOG_LOCAL4
73     fprintf( stderr, " [-l sysloguser]" );
74 #endif
75 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
76     fprintf( stderr, " [-u user] [-g group]" );
77 #endif
78     fprintf( stderr, "\n" );
79 }
80
81 time_t starttime;
82 struct sockaddr_in      bind_addr;
83
84 int
85 main( int argc, char **argv )
86 {
87         int             i;
88         int             inetd = 0;
89         int             rc;
90         int             tcps;
91 #ifdef LDAP_CONNECTIONLESS
92         int             udp;
93 #endif
94 #ifdef LOG_LOCAL4
95     int     syslogUser = DEFAULT_SYSLOG_USER;
96 #endif
97 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
98         char            *username = NULL, *groupname = NULL;
99 #endif
100         char            *configfile;
101         char        *serverName;
102         int         serverMode = SLAP_SERVER_MODE;
103
104         configfile = SLAPD_DEFAULT_CONFIGFILE;
105
106         (void) memset( (void*) &bind_addr, '\0', sizeof(bind_addr));
107         bind_addr.sin_family = AF_INET;
108         bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
109         bind_addr.sin_port = htons(LDAP_PORT);
110
111         g_argc = argc;
112         g_argv = argv;
113
114         while ( (i = getopt( argc, argv,
115                              "d:f:ia:p:s:"
116 #ifdef LOG_LOCAL4
117                              "l:"
118 #endif
119 #ifdef SLAPD_BDB2
120                              "t"
121 #endif
122 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
123                              "u:g:"
124 #endif
125 #ifdef LDAP_CONNECTIONLESS
126                                  "c"
127 #endif
128                              )) != EOF ) {
129                 switch ( i ) {
130                 case 'a':       /* bind address */
131 #ifdef HAVE_WINSOCK
132                         if(!(bind_addr.sin_addr.S_un.S_addr = inet_addr(optarg)))
133 #else
134                         if(!inet_aton(optarg, &bind_addr.sin_addr))
135 #endif
136                         {
137                                 fprintf(stderr, "invalid address (%s) for -a option", optarg);
138                         }
139             break;
140
141 #ifdef LDAP_DEBUG
142                 case 'd':       /* turn on debugging */
143                         if ( optarg[0] == '?' ) {
144                                 printf( "Debug levels:\n" );
145                                 printf( "\tLDAP_DEBUG_TRACE\t%d\n",
146                                     LDAP_DEBUG_TRACE );
147                                 printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
148                                     LDAP_DEBUG_PACKETS );
149                                 printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
150                                     LDAP_DEBUG_ARGS );
151                                 printf( "\tLDAP_DEBUG_CONNS\t%d\n",
152                                     LDAP_DEBUG_CONNS );
153                                 printf( "\tLDAP_DEBUG_BER\t\t%d\n",
154                                     LDAP_DEBUG_BER );
155                                 printf( "\tLDAP_DEBUG_FILTER\t%d\n",
156                                     LDAP_DEBUG_FILTER );
157                                 printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
158                                     LDAP_DEBUG_CONFIG );
159                                 printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
160                                     LDAP_DEBUG_ACL );
161                                 printf( "\tLDAP_DEBUG_STATS\t%d\n",
162                                     LDAP_DEBUG_STATS );
163                                 printf( "\tLDAP_DEBUG_STATS2\t%d\n",
164                                     LDAP_DEBUG_STATS2 );
165                                 printf( "\tLDAP_DEBUG_SHELL\t%d\n",
166                                     LDAP_DEBUG_SHELL );
167                                 printf( "\tLDAP_DEBUG_PARSE\t%d\n",
168                                     LDAP_DEBUG_PARSE );
169                                 printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
170                                     LDAP_DEBUG_ANY );
171                                 exit( 0 );
172                         } else {
173                                 slap_debug |= atoi( optarg );
174                         }
175                         break;
176 #else
177                 case 'd':       /* turn on debugging */
178                         fprintf( stderr,
179                             "must compile with LDAP_DEBUG for debugging\n" );
180                         break;
181 #endif
182
183                 case 'f':       /* read config file */
184                         configfile = ch_strdup( optarg );
185                         break;
186
187                 case 'i':       /* run from inetd */
188                         inetd = 1;
189                         break;
190
191                 case 'p': {     /* port on which to listen */
192                                 short port = (short)atoi( optarg );
193                                 if(! port ) {
194                                         fprintf(stderr, "-p %s must be numeric\n", optarg);
195                                 } else {
196                                         bind_addr.sin_port = htons(port);
197                                 }
198                         } break;
199
200                 case 's':       /* set syslog level */
201                         ldap_syslog = atoi( optarg );
202                         break;
203
204 #ifdef LOG_LOCAL4
205                 case 'l':       /* set syslog local user */
206                         syslogUser = cnvt_str2int( optarg, syslog_types,
207                                            DEFAULT_SYSLOG_USER );
208                         break;
209 #endif
210
211 #ifdef LDAP_CONNECTIONLESS
212                 case 'c':       /* do connectionless (udp) */
213                         udp = 1;
214                         break;
215 #endif
216
217 #ifdef SLAPD_BDB2
218                 case 't':  /* timed server */
219                         serverMode = SLAP_TIMEDSERVER_MODE;
220                         break;
221 #endif
222
223 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
224                 case 'u':       /* user name */
225                         if( username ) free(username);
226                         username = ch_strdup( optarg );
227                         break;
228
229                 case 'g':       /* group name */
230                         if( groupname ) free(groupname);
231                         groupname = ch_strdup( optarg );
232                         break;
233 #endif /* SETUID && GETUID */
234
235                 default:
236                         usage( argv[0] );
237                         exit( 1 );
238                 }
239         }
240
241         ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
242         ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
243         ldif_debug = slap_debug;
244
245         Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
246
247         if ( (serverName = strrchr( argv[0], '/' )) == NULL ) {
248                 serverName = ch_strdup( argv[0] );
249         } else {
250                 serverName = ch_strdup( serverName + 1 );
251         }
252
253 #ifdef LOG_LOCAL4
254         openlog( serverName, OPENLOG_OPTIONS, syslogUser );
255 #else
256         openlog( serverName, OPENLOG_OPTIONS );
257 #endif
258
259         tcps = set_socket( inetd ? NULL : &bind_addr );
260
261 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
262         if ( username != NULL || groupname != NULL )
263                 slap_init_user( username, groupname );
264 #endif
265
266         if ( slap_init( serverMode, serverName ) != 0 ) {
267                 rc = 1;
268                 goto destroy;
269         }
270
271         if ( read_config( configfile ) != 0 ) {
272                 rc = 1;
273                 goto destroy;
274         }
275
276         (void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
277         (void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
278 #ifdef SIGPIPE
279         (void) SIGNAL( SIGPIPE, SIG_IGN );
280 #endif
281 #ifdef SIGHUP
282         (void) SIGNAL( SIGHUP, slap_set_shutdown );
283 #endif
284         (void) SIGNAL( SIGINT, slap_set_shutdown );
285         (void) SIGNAL( SIGTERM, slap_set_shutdown );
286 #ifdef LDAP_SIGCHLD
287         (void) SIGNAL( LDAP_SIGCHLD, wait4child );
288 #endif
289
290 #ifndef WIN32
291         if(!inetd) {
292 #ifdef LDAP_DEBUG
293                 lutil_detach( ldap_debug, 0 );
294 #else
295                 lutil_detach( 0, 0 );
296 #endif
297         }
298 #endif /* WIN32 */
299
300         if ( slap_startup(-1)  != 0 ) {
301                 rc = 1;
302                 goto shutdown;
303         }
304
305         if(!inetd) {
306                 FILE *fp;
307
308                 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
309
310                 if (( slapd_pid_file != NULL ) &&
311                         (( fp = fopen( slapd_pid_file, "w" )) != NULL ))
312                 {
313                         fprintf( fp, "%d\n", (int) getpid() );
314                         fclose( fp );
315                 }
316
317                 if (( slapd_args_file != NULL ) &&
318                         (( fp = fopen( slapd_args_file, "w" )) != NULL ))
319                 {
320                         for ( i = 0; i < g_argc; i++ ) {
321                                 fprintf( fp, "%s ", g_argv[i] );
322                         }
323                         fprintf( fp, "\n" );
324                         fclose( fp );
325                 }
326         }
327
328         time( &starttime );
329
330         rc = slapd_daemon( inetd, tcps );
331
332 shutdown:
333         /* remember an error during shutdown */
334         rc |= slap_shutdown(-1);
335 destroy:
336         /* remember an error during destroy */
337         rc |= slap_destroy();
338
339         Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
340
341         closelog();
342
343         return rc;
344 }
345
346
347 #ifdef LDAP_SIGCHLD
348
349 /*
350  *  Catch and discard terminated child processes, to avoid zombies.
351  */
352
353 static RETSIGTYPE
354 wait4child( int sig )
355 {
356     int save_errno = errno;
357
358 #ifdef WNOHANG
359     errno = 0;
360 #ifdef HAVE_WAITPID
361     while ( waitpid( (pid_t)-1, NULL, WNOHANG ) >= 0 || errno == EINTR )
362         ;       /* NULL */
363 #else
364     while ( wait3( NULL, WNOHANG, NULL ) >= 0 || errno == EINTR )
365         ;       /* NULL */
366 #endif
367 #else
368     (void) wait( NULL );
369 #endif
370     (void) SIGNAL( sig, wait4child );
371     errno = save_errno;
372 }
373
374 #endif /* SIGCHLD || SIGCLD */
375
376
377 #ifdef LOG_LOCAL4
378
379 /*
380  *  Convert a string to an integer by means of a dispatcher table
381  *  if the string is not in the table return the default
382  */
383
384 static int
385 cnvt_str2int( char *stringVal, STRDISP_P dispatcher, int defaultVal )
386 {
387     int        retVal = defaultVal;
388     STRDISP_P  disp;
389
390     for (disp = dispatcher; disp->stringVal; disp++) {
391
392         if (!strncasecmp (stringVal, disp->stringVal, disp->abbr)) {
393
394             retVal = disp->intVal;
395             break;
396
397         }
398     }
399
400     return (retVal);
401
402 } /* cnvt_str2int */
403
404 #endif  /* LOG_LOCAL4 */