Example #1
0
int main(int argc, char **argv) {
    int i;
    int config_loaded = 0;
    int dont_fork = 0;
    size_t default_stacksize;

    // set the name for logging
    program_name = "netdata";

    // parse depercated options
    // TODO: Remove this block with the next major release.
    {
        i = 1;
        while(i < argc) {
            if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) {
                strncpyz(pidfile, argv[i+1], FILENAME_MAX);
                fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) {
                dont_fork = 1;
                fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) {
                config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]);
                fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) {
                config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]);
                fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else i++;
        }
    }

    // parse options
    {
        int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
        char optstring[(num_opts * 2) + 1];

        int string_i = 0;
        for( i = 0; i < num_opts; i++ ) {
            optstring[string_i] = option_definitions[i].val;
            string_i++;
            if(option_definitions[i].arg_name) {
                optstring[string_i] = ':';
                string_i++;
            }
        }
        // terminate optstring
        optstring[string_i] ='\0';
        optstring[(num_opts *2)] ='\0';

        int opt;
        while( (opt = getopt(argc, argv, optstring)) != -1 ) {
            switch(opt) {
                case 'c':
                    if(config_load(optarg, 1) != 1) {
                        error("Cannot load configuration file %s.", optarg);
                        return 1;
                    }
                    else {
                        debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
                        config_loaded = 1;
                    }
                    break;
                case 'D':
                    dont_fork = 1;
                    break;
                case 'h':
                    return help(0);
                case 'i':
                    config_set(CONFIG_SECTION_WEB, "bind to", optarg);
                    break;
                case 'P':
                    strncpy(pidfile, optarg, FILENAME_MAX);
                    pidfile[FILENAME_MAX] = '\0';
                    break;
                case 'p':
                    config_set(CONFIG_SECTION_GLOBAL, "default port", optarg);
                    break;
                case 's':
                    config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg);
                    break;
                case 't':
                    config_set(CONFIG_SECTION_GLOBAL, "update every", optarg);
                    break;
                case 'u':
                    config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg);
                    break;
                case 'v':
                case 'V':
                    printf("%s %s\n", program_name, program_version);
                    return 0;
                case 'W':
                    {
                        char* stacksize_string = "stacksize=";
                        char* debug_flags_string = "debug_flags=";

                        if(strcmp(optarg, "unittest") == 0) {
                            if(unit_test_buffer()) return 1;
                            if(unit_test_str2ld()) return 1;
                            //default_rrd_update_every = 1;
                            //default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
                            //if(!config_loaded) config_load(NULL, 0);
                            get_netdata_configured_variables();
                            default_rrd_update_every = 1;
                            default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
                            default_health_enabled = 0;
                            rrd_init("unittest");
                            default_rrdpush_enabled = 0;
                            if(run_all_mockup_tests()) return 1;
                            if(unit_test_storage()) return 1;
                            fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
                            return 0;
                        }
                        else if(strcmp(optarg, "simple-pattern") == 0) {
                            if(optind + 2 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
                                        " Checks if 'pattern' matches the given 'string'.\n"
                                        " - 'pattern' can be one or more space separated words.\n"
                                        " - each 'word' can contain one or more asterisks.\n"
                                        " - words starting with '!' give negative matches.\n"
                                        " - words are processed left to right\n"
                                        "\n"
                                        "Examples:\n"
                                        "\n"
                                        " > match all veth interfaces, except veth0:\n"
                                        "\n"
                                        "   -W simple-pattern '!veth0 veth*' 'veth12'\n"
                                        "\n"
                                        "\n"
                                        " > match all *.ext files directly in /path/:\n"
                                        "   (this will not match *.ext files in a subdir of /path/)\n"
                                        "\n"
                                        "   -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
                                        "\n"
                                );
                                return 1;
                            }

                            const char *heystack = argv[optind];
                            const char *needle = argv[optind + 1];
                            size_t len = strlen(needle) + 1;
                            char wildcarded[len];

                            SIMPLE_PATTERN *p = simple_pattern_create(heystack, NULL, SIMPLE_PATTERN_EXACT);
                            int ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
                            simple_pattern_free(p);

                            if(ret) {
                                fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
                                return 0;
                            }
                            else {
                                fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
                                return 1;
                            }
                        }
                        else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
                            optarg += strlen(stacksize_string);
                            config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg);
                        }
                        else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
                            optarg += strlen(debug_flags_string);
                            config_set(CONFIG_SECTION_GLOBAL, "debug flags",  optarg);
                            debug_flags = strtoull(optarg, NULL, 0);
                        }
                        else if(strcmp(optarg, "set") == 0) {
                            if(optind + 3 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n"
                                        " Overwrites settings of netdata.conf.\n"
                                        "\n"
                                        " These options interact with: -c netdata.conf\n"
                                        " If -c netdata.conf is given on the command line,\n"
                                        " before -W set... the user may overwrite command\n"
                                        " line parameters at netdata.conf\n"
                                        " If -c netdata.conf is given after (or missing)\n"
                                        " -W set... the user cannot overwrite the command line\n"
                                        " parameters."
                                        "\n"
                                );
                                return 1;
                            }
                            const char *section = argv[optind];
                            const char *key = argv[optind + 1];
                            const char *value = argv[optind + 2];
                            optind += 3;

                            // set this one as the default
                            // only if it is not already set in the config file
                            // so the caller can use -c netdata.conf before or
                            // after this parameter to prevent or allow overwriting
                            // variables at netdata.conf
                            config_set_default(section, key,  value);

                            // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
                        }
                        else if(strcmp(optarg, "get") == 0) {
                            if(optind + 3 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n"
                                        " Prints settings of netdata.conf.\n"
                                        "\n"
                                        " These options interact with: -c netdata.conf\n"
                                        " -c netdata.conf has to be given before -W get.\n"
                                        "\n"
                                );
                                return 1;
                            }

                            if(!config_loaded) {
                                fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
                                config_load(NULL, 0);
                            }

                            backwards_compatible_config();
                            get_netdata_configured_variables();

                            const char *section = argv[optind];
                            const char *key = argv[optind + 1];
                            const char *def = argv[optind + 2];
                            const char *value = config_get(section, key, def);
                            printf("%s\n", value);
                            return 0;
                        }
                        else {
                            fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
                            return help(1);
                        }
                    }
                    break;

                default: /* ? */
                    fprintf(stderr, "Unknown parameter '%c'\n", opt);
                    return help(1);
            }
        }
    }

#ifdef _SC_OPEN_MAX
    // close all open file descriptors, except the standard ones
    // the caller may have left open files (lxc-attach has this issue)
    {
        int fd;
        for(fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--)
            if(fd_is_valid(fd)) close(fd);
    }
#endif

    if(!config_loaded)
        config_load(NULL, 0);

    // ------------------------------------------------------------------------
    // initialize netdata
    {
        char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1");
        if(pmax && *pmax)
            setenv("MALLOC_ARENA_MAX", pmax, 1);

#if defined(HAVE_C_MALLOPT)
        i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1);
        if(i > 0)
            mallopt(M_ARENA_MAX, 1);
#endif

        // prepare configuration environment variables for the plugins

        get_netdata_configured_variables();
        set_global_environment();

        // work while we are cd into config_dir
        // to allow the plugins refer to their config
        // files using relative filenames
        if(chdir(netdata_configured_config_dir) == -1)
            fatal("Cannot cd to '%s'", netdata_configured_config_dir);
    }

    char *user = NULL;

    {
        // --------------------------------------------------------------------
        // get the debugging flags from the configuration file

        char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags",  "0x0000000000000000");
        setenv("NETDATA_DEBUG_FLAGS", flags, 1);

        debug_flags = strtoull(flags, NULL, 0);
        debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags);

        if(debug_flags != 0) {
            struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
            if(setrlimit(RLIMIT_CORE, &rl) != 0)
                error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");

#ifdef HAVE_SYS_PRCTL_H
            prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
        }


        // --------------------------------------------------------------------
        // get log filenames and settings

        log_init();
        error_log_limit_unlimited();


        // --------------------------------------------------------------------
        // load stream.conf
        {
            char filename[FILENAME_MAX + 1];
            snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir);
            appconfig_load(&stream_config, filename, 0);
        }


        // --------------------------------------------------------------------
        // setup process signals

        // block signals while initializing threads.
        // this causes the threads to block signals.
        signals_block();

        // setup the signals we want to use
        signals_init();

        // setup threads configs
        default_stacksize = netdata_threads_init();


        // --------------------------------------------------------------------
        // check which threads are enabled and initialize them

        for (i = 0; static_threads[i].name != NULL ; i++) {
            struct netdata_static_thread *st = &static_threads[i];

            if(st->config_name)
                st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled);

            if(st->enabled && st->init_routine)
                st->init_routine();
        }


        // --------------------------------------------------------------------
        // get the user we should run

        // IMPORTANT: this is required before web_files_uid()
        if(getuid() == 0) {
            user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER);
        }
        else {
            struct passwd *passwd = getpwuid(getuid());
            user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:"");
        }

        // --------------------------------------------------------------------
        // create the listening sockets

        web_client_api_v1_init();
        web_server_threading_selection();

        if(web_server_mode != WEB_SERVER_MODE_NONE)
            api_listen_sockets_setup();
    }

    // initialize the log files
    open_all_log_files();

#ifdef NETDATA_INTERNAL_CHECKS
    if(debug_flags != 0) {
        struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
        if(setrlimit(RLIMIT_CORE, &rl) != 0)
            error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
#ifdef HAVE_SYS_PRCTL_H
        prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
    }
#endif /* NETDATA_INTERNAL_CHECKS */

    // get the max file limit
    if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0)
        error("getrlimit(RLIMIT_NOFILE) failed");
    else
        info("resources control: allowed file descriptors: soft = %zu, max = %zu", rlimit_nofile.rlim_cur, rlimit_nofile.rlim_max);

    // fork, switch user, create pid file, set process priority
    if(become_daemon(dont_fork, user) == -1)
        fatal("Cannot daemonize myself.");

    info("netdata started on pid %d.", getpid());

    // IMPORTANT: these have to run once, while single threaded
    // but after we have switched user
    web_files_uid();
    web_files_gid();

    netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize));

    // ------------------------------------------------------------------------
    // initialize rrd, registry, health, rrdpush, etc.

    rrd_init(netdata_configured_hostname);


    // ------------------------------------------------------------------------
    // enable log flood protection

    error_log_limit_reset();


    // ------------------------------------------------------------------------
    // spawn the threads

    web_server_config_options();

    for (i = 0; static_threads[i].name != NULL ; i++) {
        struct netdata_static_thread *st = &static_threads[i];

        if(st->enabled) {
            st->thread = mallocz(sizeof(netdata_thread_t));
            debug(D_SYSTEM, "Starting thread %s.", st->name);
            netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
        }
        else debug(D_SYSTEM, "Not starting thread %s.", st->name);
    }

    info("netdata initialization completed. Enjoy real-time performance monitoring!");


    // ------------------------------------------------------------------------
    // unblock signals

    signals_unblock();

    // ------------------------------------------------------------------------
    // Handle signals

    signals_handle();

    // should never reach this point
    // but we need it for rpmlint #2752
    return 1;
}
Example #2
0
File: main.c Project: B-Rich/smart
/* Open LDAP and Notifier connection.
 * @return 0 on success, 1 on error.
 */
static int do_connection(univention_ldap_parameters_t *lp)
{
	LDAPMessage *res;
	int rc;
	struct timeval timeout = {
		.tv_sec = 10,
		.tv_usec = 0,
	};

	if (univention_ldap_open(lp) != LDAP_SUCCESS)
		goto fail;
	if (notifier_client_new(NULL, lp->host, 1) != 0)
		goto fail;

	/* check if we are connected to an OpenLDAP */
	rc = ldap_search_ext_s(lp->ld, lp->base, LDAP_SCOPE_BASE, "objectClass=univentionBase",
			NULL, 0, NULL, NULL, &timeout, 0, &res);
	ldap_msgfree(res);
	switch (rc) {
		case LDAP_SUCCESS:
			return 0;
		case LDAP_NO_SUCH_OBJECT:
			univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR,
					"Failed to find \"(objectClass=univentionBase)\" on LDAP server %s:%d", lp->host, lp->port);
			break;
		default:
			univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR,
					"Failed to search for \"(objectClass=univentionBase)\" on LDAP server %s:%d with message %s", lp->host, lp->port, ldap_err2string(rc));
			break;
	}
fail:
	notifier_client_destroy(NULL);
	if (lp->ld)
		ldap_unbind_ext(lp->ld, NULL, NULL);
	lp->ld = NULL;
	return 1;
}


int main(int argc, char* argv[])
{
	univention_ldap_parameters_t	*lp;
	univention_ldap_parameters_t	*lp_local;
	char *server_role;
#ifdef WITH_KRB5
	univention_krb5_parameters_t	*kp = NULL;
	bool do_kinit = false;
#else
	void				*kp = NULL ;
#endif
	int debugging = 0;
	bool from_scratch = false;
	bool foreground = false;
	bool initialize_only = false;
	bool write_transaction_file = false;
	int				 rv;
	NotifierID			 id = -1;
#ifndef WITH_DB42
	NotifierID			 old_id = -1;
#else
	CacheMasterEntry		 master_entry;
#endif
	struct stat			 stbuf;
	char *f = NULL;

	univention_debug_init("stderr", 1, 1);

	if ((lp = univention_ldap_new()) == NULL)
		exit(1);
	lp->authmethod = LDAP_AUTH_SASL;

	if ((lp_local = univention_ldap_new()) == NULL)
		exit(1);

#if WITH_KRB5
	if ((kp=univention_krb5_new()) == NULL)
		exit(1);
#endif

	/* parse arguments */
	for (;;) {
		int c;

		c = getopt(argc, argv, "d:FH:h:p:b:D:w:y:xZY:U:R:Km:Bc:giol:");
		if (c < 0)
			break;
		switch (c) {
		case 'd':
			debugging=atoi(optarg);
			break;
		case 'F':
			foreground = true;
			break;
		case 'H':
			lp->uri=strdup(optarg);
			break;
		case 'h':
			lp->host=strdup(optarg);
			break;
		case 'p':
			lp->port=atoi(optarg);
			break;
		case 'b':
			lp->base=strdup(optarg);
			break;
		case 'm':
			if ((module_dirs = realloc(module_dirs, (module_dir_count+2)*sizeof(char*))) == NULL) {
				return 1;
			}
			module_dirs[module_dir_count] = strdup(optarg);
			module_dirs[module_dir_count+1] = NULL;
			module_dir_count++;
			break;
		case 'c':
			cache_dir=strdup(optarg);
			break;
		case 'l':
			ldap_dir = strdup(optarg);
			if (asprintf(&transaction_file, "%s/listener/listener", ldap_dir) < 0) abort();
			break;
		case 'D':
			lp->binddn=strdup(optarg);
			break;
		case 'w':
			lp->bindpw=strdup(optarg);
#ifdef WITH_KRB5
			kp->password=strdup(optarg);
#endif
			/* remove password from process list */
			memset(optarg, 'X', strlen(optarg));
			break;
		case 'Z':
			lp->start_tls++;
			break;
		case 'x':
			lp->authmethod = LDAP_AUTH_SIMPLE;
			break;
		case 'y':
			lp->bindpw=read_pwd_from_file(optarg);
#ifdef WITH_KRB5
			kp->password=strdup(lp->bindpw);
#endif
			break;
		case 'Y':
			lp->sasl_mech=strdup(optarg);
			break;
		case 'U':
			asprintf(&lp->sasl_authzid, "u:%s", optarg);
			/* kp->username=strdup(optarg); */
		case 'R':
			lp->sasl_realm=strdup(optarg);
#ifdef WITH_KRB5
			kp->realm=strdup(optarg);
#endif
			break;
#ifdef WITH_KRB5
		case 'K':
			do_kinit = true;
			break;
#endif
		case 'g':
			from_scratch = true;
			break;
		case 'i':
			initialize_only = true;
			from_scratch = true;
			foreground = true;
			break;
		case 'o':
			write_transaction_file = true;
			break;
		case 'B':
			backup_notifier = 1;
			break;
		default:
			usage();
			exit(1);
		}
	}

	if (asprintf(&f, "%s/bad_cache", cache_dir) < 0) abort();
	if (stat(f, &stbuf) == 0) {
		exit(3);
	}
	free(f);

	univention_debug_set_level(UV_DEBUG_LISTENER, debugging);
	univention_debug_set_level(UV_DEBUG_LDAP, debugging);
	univention_debug_set_level(UV_DEBUG_KERBEROS, debugging);

	snprintf(pidfile, PATH_MAX, "%s/pid", cache_dir);
	signals_init();

	if (!foreground && daemonize() != 0)
		exit(EXIT_FAILURE);

	drop_privileges();

	if (from_scratch)
		purge_cache(cache_dir);

	prepare_cache(cache_dir);

	/* choose server to connect to */
	if (lp->host == NULL && lp->uri == NULL) {
		select_server(lp);
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO,
				"no server given, choosing one by myself (%s)",
				lp->host);
	}

#ifdef WITH_KRB5
	if (!do_kinit)
		kp = NULL;
	if (kp != NULL && univention_krb5_init(kp) != 0) {
		univention_debug(UV_DEBUG_KERBEROS, UV_DEBUG_ERROR, "kinit failed");
		exit(1);
	}
#endif

	while (do_connection(lp) != 0) {
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_WARN, "can not connect to ldap server %s:%d", lp->host, lp->port);
		if (suspend_connect()) {
			if (initialize_only) {
				univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR,
					"can not connect to any ldap server, exit");
				exit(1);
			}
			univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_WARN,
				"can not connect to any ldap server, retrying in 30 seconds");
			sleep(30);
		}

		select_server(lp);
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_WARN, "chosen server: %s:%d", lp->host, lp->port);
	}

	univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, "connection okay to host %s:%d", lp->host, lp->port);

	/* connect to local LDAP server */
	server_role = univention_config_get_string("server/role");
	if ( server_role != NULL ) {
		if (!strcmp(server_role, "domaincontroller_backup") || !strcmp(server_role, "domaincontroller_slave")) {	// if not master
			lp_local->host = strdup("localhost"); // or fqdn e.g. from univention_config_get_string("ldap/server/name");
			lp_local->base = strdup(lp->base);
			lp_local->binddn = strdup(lp->binddn);
			lp_local->bindpw = strdup(lp->bindpw);
		}
		free(server_role);
	}

	/* XXX: we shouldn't block all signals for so long */
	signals_block();
	cache_init();
	handlers_init();

	/* pass data to handlers */
	if (lp->base != NULL)
		handlers_set_data_all("basedn", lp->base);
	if (lp->binddn != NULL)
		handlers_set_data_all("binddn", lp->binddn);
	if (lp->bindpw != NULL)
		handlers_set_data_all("bindpw", lp->bindpw);
	if (lp->host != NULL)
		handlers_set_data_all("ldapserver", lp->host);

	convert_cookie();

	if (notifier_get_id_s(NULL, &id) != 0) {
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "failed to receive current ID");
		return 1;
	}

	if (initialize_only) {
		INIT_ONLY=1;
	}

	/* update schema */
	if ((rv=change_update_schema(lp)) != LDAP_SUCCESS)
		return rv;

	/* do initial import of entries */
	if ((rv=change_new_modules(lp)) != LDAP_SUCCESS) {
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "change_new_modules: %s", ldap_err2string(rv));
		return rv;
	}
	signals_unblock();

	/* if no ID is set, assume the database has just been initialized */
#ifdef WITH_DB42
	if ((rv=cache_get_master_entry(&master_entry)) == DB_NOTFOUND) {
		master_entry.id = id;
		if ((rv=cache_update_master_entry(&master_entry, NULL)) != 0)
			exit(1);
	} else if (rv != 0)
		exit(1);

#else
	cache_get_int("notifier_id", &old_id, -1);
	if ((long)old_id == -1) {
		cache_set_int("notifier_id", id);
	}
#endif

	if (!initialize_only) {
		rv = notifier_listen(lp, kp, write_transaction_file, lp_local);
	}

	if (rv != 0)
		univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, "listener: %d", rv);

	univention_ldap_close(lp);
	univention_ldap_close(lp_local);

	exit_handler(0);
}