]> git.sur5r.net Git - openldap/blobdiff - servers/slurpd/config.c
allow per-replogfile pid/args file & replication interval (ITS#3523)
[openldap] / servers / slurpd / config.c
index 6f3df19a0f95444217954371795a6984a7248d74..4ab518f5e6e8d1e7ea00794efec7a90ffa1dedbf 100644 (file)
@@ -1,10 +1,20 @@
 /* $OpenLDAP$ */
-/*
- * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Portions Copyright 2003 Mark Benson.
+ * Portions Copyright 2002 John Morrissey.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
  */
-/*
- * Copyright (c) 1996 Regents of the University of Michigan.
+/* Portions Copyright (c) 1996 Regents of the University of Michigan.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).  Additional signficant contributors
+ * include:
+ *    John Morrissey
+ *    Mark Benson
+ */
 
 
 /*
@@ -30,6 +47,7 @@
 #include <ac/ctype.h>
 
 #include <ldap.h>
+#include <lutil.h>
 
 #include "slurp.h"
 #include "globals.h"
@@ -40,7 +58,7 @@
 static void    add_replica LDAP_P(( char **, int ));
 static int     parse_replica_line LDAP_P(( char **, int, Ri *));
 static void    parse_line LDAP_P(( char * ));
-static char    *getline LDAP_P(( FILE * ));
+static char    *slurpd_getline LDAP_P(( FILE * ));
 static char    *strtok_quote LDAP_P(( char *, char * ));
 
 int    cargc = 0, cargv_size = 0;
@@ -61,147 +79,224 @@ slurpd_read_config(
     char       *fname
 )
 {
-    FILE       *fp;
-    char       *line;
-
-       cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
-       cargv_size = ARGS_STEP + 1;
+       FILE    *fp;
+       char    *line;
+
+#define GOT_REPLOG_NO          (0)
+#define GOT_REPLOG_ONE         (1)
+#define GOT_REPLOG_YES         (2)     
+#define GOT_REPLOG_DONE                (3)
+#define        GOT_REPLOG_MASK         (0xF)
+#define        GOT_REPLOG(i)           ((i) & GOT_REPLOG_MASK)
+#define        GOT_REPLOG_SET(i,v)     ((i) = ((i) & ~GOT_REPLOG_MASK) | ((v) & GOT_REPLOG_MASK))
+
+#define GOT_REPLOG_PID         (0x10)
+#define GOT_REPLOG_ARGS                (0x20)
+#define GOT_REPLOG_INTERVAL    (0x40)
+       int     got_replog =    GOT_REPLOG_NO;
+
+       /*
+        * replica-pidfile and replica-argsfile can appear before any replog;
+        * in this case they're global (legacy behavior); otherwise, since
+        * each replog needs a slurpd, they can appear after a replogfile line;
+        * in that case, the replog specific values are used.
+        */
+
+       if ( cargv == NULL ) {
+               cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
+               cargv_size = ARGS_STEP + 1;
+       }
 
-#ifdef NEW_LOGGING
-    LDAP_LOG ( CONFIG, ARGS, 
-               "slurpd_read_config: Config: opening config file \"%s\"\n", 
+       Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
                fname, 0, 0 );
-#else
-    Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
-           fname, 0, 0 );
-#endif
-
-    if ( (fp = fopen( fname, "r" )) == NULL ) {
-       perror( fname );
-       exit( EXIT_FAILURE );
-    }
 
-    lineno = 0;
-    while ( (line = getline( fp )) != NULL ) {
-       /* skip comments and blank lines */
-       if ( line[0] == '#' || line[0] == '\0' ) {
-           continue;
+       if ( (fp = fopen( fname, "r" )) == NULL ) {
+               perror( fname );
+               exit( EXIT_FAILURE );
        }
 
-#ifdef NEW_LOGGING
-    LDAP_LOG ( CONFIG, DETAIL1, 
-               "slurpd_read_config: Config: (%s)\n", line, 0, 0 );
-#else
-       Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
-#endif
+       lineno = 0;
+       while ( (line = slurpd_getline( fp )) != NULL ) {
+               /* skip comments and blank lines */
+               if ( line[0] == '#' || line[0] == '\0' ) {
+                       continue;
+               }
 
-       parse_line( line );
+               Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
 
-       if ( cargc < 1 ) {
-           fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
-           continue;
-       }
+               parse_line( line );
 
-       /* replication log file to which changes are appended */
-       if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
-           /* 
-            * if slapd_replogfile has a value, the -r option was given,
-            * so use that value.  If slapd_replogfile has length == 0,
-            * then we should use the value in the config file we're reading.
-            */
-           if ( sglob->slapd_replogfile[ 0 ] == '\0' ) {
-               if ( cargc < 2 ) {
-                   fprintf( stderr,
-                       "line %d: missing filename in \"replogfile ",
-                       lineno );
-                   fprintf( stderr, "<filename>\" line\n" );
-                   exit( EXIT_FAILURE );
-               } else if ( cargc > 2 && *cargv[2] != '#' ) {
-                   fprintf( stderr,
-                       "line %d: extra cruft at the end of \"replogfile %s\"",
-                       lineno, cargv[1] );
-                   fprintf( stderr, "line (ignored)\n" );
+               if ( cargc < 1 ) {
+                       fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
+                       continue;
                }
-               strcpy( sglob->slapd_replogfile, cargv[1] );
-           }
-       } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
-           add_replica( cargv, cargc );
+
+               /* replication log file to which changes are appended */
+               if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
+                       /* 
+                        * if slapd_replogfile has a value, the -r option was given,
+                        * so use that value.  If slapd_replogfile has length == 0,
+                        * then we should use the value in the config file we're reading.
+                        */
+                       if ( cargc < 2 ) {
+                               fprintf( stderr,
+                                       "line %d: missing filename in \"replogfile ",
+                                       lineno );
+                               fprintf( stderr, "<filename>\" line\n" );
+                               exit( EXIT_FAILURE );
+
+                       } else if ( cargc > 2 && *cargv[2] != '#' ) {
+                               fprintf( stderr,
+                                       "line %d: extra cruft at the end of \"replogfile %s\"",
+                                       lineno, cargv[1] );
+                               fprintf( stderr, "line (ignored)\n" );
+                       }
+
+                       LUTIL_SLASHPATH( cargv[1] );
+                       if ( sglob->slapd_replogfile[0] == '\0' ) {
+                               strcpy( sglob->slapd_replogfile, cargv[1] );
+                               GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
+
+                       } else {
+                               if ( strcmp( sglob->slapd_replogfile, cargv[1] ) == 0 ) {
+                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_YES);
+
+                               } else if ( GOT_REPLOG(got_replog) == GOT_REPLOG_YES ) {
+                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_DONE);
+
+                               } else {
+                                       GOT_REPLOG_SET(got_replog, GOT_REPLOG_ONE);
+                               }
+                       }
+
+               } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
+                       add_replica( cargv, cargc );
            
-           /* include another config file */
-       } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
-           char *savefname;
-           int savelineno;
-
-            if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
-                LDAP_LOG( CONFIG, CRIT,
-                        "%s: line %d: missing filename in \"include "
-                        "<filename>\" line.\n", fname, lineno , 0 );
-#else
-                Debug( LDAP_DEBUG_ANY,
-        "%s: line %d: missing filename in \"include <filename>\" line\n",
-                        fname, lineno, 0 );
-#endif
+               /* include another config file */
+               } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
+                       char *savefname;
+                       int savelineno;
+
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s: line %d: missing filename in \"include <filename>\" line\n",
+                                       fname, lineno, 0 );
                
-                return( 1 );
-            }
-           savefname = strdup( cargv[1] );
-           savelineno = lineno;
+                               return( 1 );
+                       }
+                       LUTIL_SLASHPATH( cargv[1] );
+                       savefname = strdup( cargv[1] );
+                       savelineno = lineno;
            
-           if ( slurpd_read_config( savefname ) != 0 ) {
-               return( 1 );
-           }
+                       if ( slurpd_read_config( savefname ) != 0 ) {
+                               return( 1 );
+                       }
                
-           free( savefname );
-           lineno = savelineno - 1;
-
-       } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) {
-               if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
-                       LDAP_LOG( CONFIG, CRIT, 
-                               "%s: line %d missing file name in \"replica-pidfile <file>\" "
-                               "line.\n", fname, lineno, 0 );
-#else
-                       Debug( LDAP_DEBUG_ANY,
-           "%s: line %d: missing file name in \"replica-pidfile <file>\" line\n",
-                               fname, lineno, 0 );
-#endif
-
-                       return( 1 );
-               }
-
-               slurpd_pid_file = ch_strdup( cargv[1] );
-
-       } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) {
-               if ( cargc < 2 ) {
-#ifdef NEW_LOGGING
-                       LDAP_LOG( CONFIG, CRIT, 
-                                  "%s: %d: missing file name in "
-                                  "\"argsfile <file>\" line.\n",
-                                  fname, lineno, 0 );
-#else
-                       Debug( LDAP_DEBUG_ANY,
-           "%s: line %d: missing file name in \"argsfile <file>\" line\n",
-                           fname, lineno, 0 );
-#endif
-
-                       return( 1 );
+                       free( savefname );
+                       lineno = savelineno - 1;
+
+               } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) {
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s: line %d: missing file name in \"replica-pidfile <file>\" line\n",
+                                       fname, lineno, 0 );
+
+                               return( 1 );
+                       }
+
+                       switch ( GOT_REPLOG(got_replog) ) {
+                       case GOT_REPLOG_YES:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "got replog specific replica-pidfile \"%s\".\n",
+                                       fname, lineno, cargv[1] );
+                       case GOT_REPLOG_NO:
+                               LUTIL_SLASHPATH( cargv[1] );
+                               if ( slurpd_pid_file != NULL ) {
+                                       ch_free( slurpd_pid_file );
+                               }
+                               slurpd_pid_file = ch_strdup( cargv[1] );
+                               got_replog |= GOT_REPLOG_PID;
+                               break;
+
+                       default:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "replica-pidfile \"%s\" not mine.\n",
+                                       fname, lineno, cargv[1] );
+                               break;
+                       }
+
+               } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) {
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "%s: line %d: missing file name in \"argsfile <file>\" line\n",
+                                       fname, lineno, 0 );
+
+                               return( 1 );
+                       }
+
+                       switch ( GOT_REPLOG(got_replog) ) {
+                       case GOT_REPLOG_YES:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "got replog specific replica-argsfile \"%s\".\n",
+                                       fname, lineno, cargv[1] );
+                       case GOT_REPLOG_NO:
+                               LUTIL_SLASHPATH( cargv[1] );
+                               if ( slurpd_args_file != NULL ) {
+                                       ch_free( slurpd_args_file );
+                               }
+                               slurpd_args_file = ch_strdup( cargv[1] );
+                               got_replog |= GOT_REPLOG_ARGS;
+                               break;
+
+                       default:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "replica-argsfile \"%s\" not mine.\n",
+                                       fname, lineno, cargv[1] );
+                               break;
+                       }
+
+               } else if ( strcasecmp( cargv[0], "replicationinterval" ) == 0 ) {
+                       int c;
+
+                       if ( cargc < 2 ) {
+                               Debug( LDAP_DEBUG_ANY, "%s: line %d: missing interval in "
+                                       "\"replicationinterval <seconds>\" line\n",
+                                       fname, lineno, 0 );
+                               return( 1 );
+                       }
+
+                       if ( lutil_atoi( &c, cargv[1] ) != 0 || c < 1 ) {
+                               Debug( LDAP_DEBUG_ANY, "%s: line %d: invalid interval "
+                                       "(%d) in \"replicationinterval <seconds>\" line\n",
+                                       fname, lineno, c );
+
+                               return( 1 );
+                       }
+
+                       switch ( GOT_REPLOG(got_replog) ) {
+                       case GOT_REPLOG_YES:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "got replog specific replicationinterval \"%s\".\n",
+                                       fname, lineno, cargv[1] );
+                       case GOT_REPLOG_NO:
+                               sglob->no_work_interval = c;
+                               got_replog |= GOT_REPLOG_INTERVAL;
+                               break;
+
+                       default:
+                               Debug( LDAP_DEBUG_CONFIG, "%s: line %d: "
+                                       "replicationinterval \"%s\" not mine.\n",
+                                       fname, lineno, cargv[1] );
+                               break;
+                       }
                }
-
-               slurpd_args_file = ch_strdup( cargv[1] );
        }
-    }
-    fclose( fp );
-#ifdef NEW_LOGGING
-    LDAP_LOG ( CONFIG, RESULTS, 
-               "slurpd_read_config: Config: "
-               "** configuration file successfully read and parsed\n", 0, 0, 0 );
-#else
-    Debug( LDAP_DEBUG_CONFIG,
-           "Config: ** configuration file successfully read and parsed\n",
-           0, 0, 0 );
-#endif
-    return 0;
+
+       fclose( fp );
+       Debug( LDAP_DEBUG_CONFIG,
+               "Config: ** configuration file successfully read and parsed\n",
+               0, 0, 0 );
+       return 0;
 }
 
 
@@ -313,7 +408,7 @@ strtok_quote(
  * Get a line of input.
  */
 static char *
-getline(
+slurpd_getline(
     FILE *fp
 )
 {
@@ -380,19 +475,11 @@ add_replica(
        sglob->replicas[ nr - 1] = NULL;
        sglob->num_replicas--;
     } else {
-#ifdef NEW_LOGGING
-    LDAP_LOG ( CONFIG, RESULTS, 
-               "add_replica: Config: ** successfully added replica \"%s%d\"\n", 
-               sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
-               "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
-               sglob->replicas[ nr - 1 ]->ri_port, 0 );
-#else
        Debug( LDAP_DEBUG_CONFIG,
                "Config: ** successfully added replica \"%s:%d\"\n",
                sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
                "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
                sglob->replicas[ nr - 1 ]->ri_port, 0 );
-#endif
        sglob->replicas[ nr - 1]->ri_stel =
                sglob->st->st_add( sglob->st,
                sglob->replicas[ nr - 1 ] );
@@ -456,10 +543,14 @@ parse_replica_line(
            if (( hp = strchr( val, ':' )) != NULL ) {
                *hp = '\0';
                hp++;
-               ri->ri_port = atoi( hp );
+               if ( lutil_atoi( &ri->ri_port, hp ) != 0 ) {
+                   fprintf( stderr, "unable to parse port \"%s\", line %d\n",
+                           hp, lineno );
+                   return -1;
+               }
            }
            if ( ri->ri_port <= 0 ) {
-               ri->ri_port = 0;
+               ri->ri_port = LDAP_PORT;
            }
            ri->ri_hostname = strdup( val );
            gots |= GOT_HOST;
@@ -521,10 +612,10 @@ parse_replica_line(
            fprintf( stderr, "slurpd no longer supports Kerberos.\n" );
            exit( EXIT_FAILURE );
            } else if ( !strcasecmp( val, SIMPLESTR )) {
-               ri->ri_bind_method = AUTH_SIMPLE;
+               ri->ri_bind_method = LDAP_AUTH_SIMPLE;
                gots |= GOT_METHOD;
            } else if ( !strcasecmp( val, SASLSTR )) {
-               ri->ri_bind_method = AUTH_SASL;
+               ri->ri_bind_method = LDAP_AUTH_SASL;
                gots |= GOT_METHOD;
            } else {
                ri->ri_bind_method = -1;
@@ -573,14 +664,13 @@ parse_replica_line(
        }
     }
     
-       if ( ri->ri_bind_method == AUTH_SASL) {
+       if ( ri->ri_bind_method == LDAP_AUTH_SASL) {
                if ((gots & GOT_MECH) == 0) {
                        fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
                        fprintf( stderr, "slapd config file, line %d\n", lineno );
                        return -1;
                }
-       }
-       else if ( gots != GOT_ALL ) {
+       } else if ( gots != GOT_ALL ) {
                fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
                fprintf( stderr, "config file, line %d\n", lineno );
                return -1;