/* handles a host that is flapping */ void set_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold) { char *temp_buffer = NULL; if (hst == NULL) return; log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' started flapping!\n", hst->name); /* log a notice - this one is parsed by the history CGI */ nm_log(NSLOG_RUNTIME_WARNING, "HOST FLAPPING ALERT: %s;STARTED; Host appears to have started flapping (%2.1f%% change > %2.1f%% threshold)\n", hst->name, percent_change, high_threshold); /* add a non-persistent comment to the host */ nm_asprintf(&temp_buffer, "Notifications for this host are being suppressed because it was detected as having been flapping between different states (%2.1f%% change > %2.1f%% threshold). When the host state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold); add_new_host_comment(FLAPPING_COMMENT, hst->name, time(NULL), "(Naemon Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(hst->flapping_comment_id)); nm_free(temp_buffer); /* set the flapping indicator */ hst->is_flapping = TRUE; broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold); /* see if we should check to send a recovery notification out when flapping stops */ if (hst->current_state != STATE_UP && hst->current_notification_number > 0) hst->check_flapping_recovery_notification = TRUE; else hst->check_flapping_recovery_notification = FALSE; /* send a notification */ host_notification(hst, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE); return; }
/* sets or unsets an environment variable */ int set_environment_var(char *name, char *value, int set) { #ifndef HAVE_SETENV char *env_string = NULL; #endif /* we won't mess with null variable names */ if (name == NULL) return ERROR; /* set the environment variable */ if (set == TRUE) { #ifdef HAVE_SETENV setenv(name, (value == NULL) ? "" : value, 1); #else /* needed for Solaris and systems that don't have setenv() */ /* this will leak memory, but in a "controlled" way, since lost memory should be freed when the child process exits */ nm_asprintf(&env_string, "%s=%s", name, (value == NULL) ? "" : value); if (env_string) putenv(env_string); #endif } /* clear the variable */ else { #ifdef HAVE_UNSETENV unsetenv(name); #endif } return OK; }
static int test_path_access(const char *program, int mode) { char *envpath, *p, *colon; int ret, our_errno = 1500; /* outside errno range */ if (program[0] == '/' || !(envpath = getenv("PATH"))) return access(program, mode); if (!(envpath = strdup(envpath))) { errno = ENOMEM; return -1; } for (p = envpath; p; p = colon + 1) { char *path; colon = strchr(p, ':'); if (colon) *colon = 0; nm_asprintf(&path, "%s/%s", p, program); ret = access(path, mode); free(path); if (!ret) break; if (ret < 0) { if (errno == ENOENT) continue; if (our_errno > errno) our_errno = errno; } if (!colon) break; } free(envpath); if (!ret) errno = 0; else errno = our_errno; return ret; }
/* handles a service that is flapping */ void set_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) { char *temp_buffer = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "set_service_flap()\n"); if (svc == NULL) return; log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' started flapping!\n", svc->description, svc->host_name); /* log a notice - this one is parsed by the history CGI */ logit(NSLOG_RUNTIME_WARNING, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STARTED; Service appears to have started flapping (%2.1f%% change >= %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, high_threshold); /* add a non-persistent comment to the service */ nm_asprintf(&temp_buffer, "Notifications for this service are being suppressed because it was detected as having been flapping between different states (%2.1f%% change >= %2.1f%% threshold). When the service state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold); add_new_service_comment(FLAPPING_COMMENT, svc->host_name, svc->description, time(NULL), "(Naemon Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(svc->flapping_comment_id)); my_free(temp_buffer); /* set the flapping indicator */ svc->is_flapping = TRUE; #ifdef USE_EVENT_BROKER /* send data to event broker */ broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL); #endif /* see if we should check to send a recovery notification out when flapping stops */ if (svc->current_state != STATE_OK && svc->current_notification_number > 0) svc->check_flapping_recovery_notification = TRUE; else svc->check_flapping_recovery_notification = FALSE; /* send a notification */ if (allow_flapstart_notification == TRUE) service_notification(svc, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE); return; }
/* runs a host event handler command */ static int run_host_event_handler(nagios_macros *mac, const host * const hst) { char *raw_command = NULL; char *processed_command = NULL; char *raw_logentry = NULL; char *processed_logentry = NULL; char *command_output = NULL; int early_timeout = FALSE; double exectime = 0.0; int result = 0; struct timeval start_time; struct timeval end_time; int neb_result = OK; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; if (hst == NULL) return ERROR; /* bail if there's no command */ if (hst->event_handler == NULL) return ERROR; log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running event handler for host '%s'..\n", hst->name); /* get start time */ gettimeofday(&start_time, NULL); get_raw_command_line_r(mac, hst->event_handler_ptr, hst->event_handler, &raw_command, macro_options); if (raw_command == NULL) return ERROR; log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw host event handler command line: %s\n", raw_command); /* process any macros in the raw command line */ process_macros_r(mac, raw_command, &processed_command, macro_options); nm_free(raw_command); if (processed_command == NULL) return ERROR; log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed host event handler command line: %s\n", processed_command); if (log_event_handlers == TRUE) { nm_asprintf(&raw_logentry, "HOST EVENT HANDLER: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n", hst->name, hst->event_handler); process_macros_r(mac, raw_logentry, &processed_logentry, macro_options); nm_log(NSLOG_EVENT_HANDLER, "%s", processed_logentry); } end_time.tv_sec = 0L; end_time.tv_usec = 0L; neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, NULL); /* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */ if (neb_result == NEBERROR_CALLBACKOVERRIDE) { nm_free(processed_command); nm_free(raw_logentry); nm_free(processed_logentry); return OK; } /* run the command through a worker */ result = wproc_run_callback(processed_command, event_handler_timeout, event_handler_job_handler, "Host", mac); /* check to see if the event handler timed out */ if (early_timeout == TRUE) nm_log(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, "Warning: Host event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout); /* get end time */ gettimeofday(&end_time, NULL); broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, command_output); nm_free(command_output); nm_free(processed_command); nm_free(raw_logentry); nm_free(processed_logentry); return OK; }
/* runs the global service event handler */ static int run_global_service_event_handler(nagios_macros *mac, service *svc) { char *raw_command = NULL; char *processed_command = NULL; char *raw_logentry = NULL; char *processed_logentry = NULL; char *command_output = NULL; int early_timeout = FALSE; double exectime = 0.0; int result = 0; struct timeval start_time; struct timeval end_time; int neb_result = OK; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; if (svc == NULL) return ERROR; /* bail out if we shouldn't be running event handlers */ if (enable_event_handlers == FALSE) return OK; /* a global service event handler command has not been defined */ if (global_service_event_handler == NULL) return ERROR; log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running global event handler for service '%s' on host '%s'...\n", svc->description, svc->host_name); /* get start time */ gettimeofday(&start_time, NULL); get_raw_command_line_r(mac, global_service_event_handler_ptr, global_service_event_handler, &raw_command, macro_options); if (raw_command == NULL) { return ERROR; } log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw global service event handler command line: %s\n", raw_command); /* process any macros in the raw command line */ process_macros_r(mac, raw_command, &processed_command, macro_options); nm_free(raw_command); if (processed_command == NULL) return ERROR; log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed global service event handler command line: %s\n", processed_command); if (log_event_handlers == TRUE) { nm_asprintf(&raw_logentry, "GLOBAL SERVICE EVENT HANDLER: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n", svc->host_name, svc->description, global_service_event_handler); process_macros_r(mac, raw_logentry, &processed_logentry, macro_options); nm_log(NSLOG_EVENT_HANDLER, "%s", processed_logentry); } end_time.tv_sec = 0L; end_time.tv_usec = 0L; neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, NULL); /* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */ if (neb_result == NEBERROR_CALLBACKOVERRIDE) { nm_free(processed_command); nm_free(raw_logentry); nm_free(processed_logentry); return OK; } /* run the command through a worker */ result = wproc_run_callback(processed_command, event_handler_timeout, event_handler_job_handler, "Global service", mac); /* check to see if the event handler timed out */ if (early_timeout == TRUE) nm_log(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, "Warning: Global service event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout); /* get end time */ gettimeofday(&end_time, NULL); broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, command_output); nm_free(command_output); nm_free(processed_command); nm_free(raw_logentry); nm_free(processed_logentry); return OK; }
int main(int argc, char **argv) { int result; int error = FALSE; int display_license = FALSE; int display_help = FALSE; int c = 0; int allow_root = FALSE; struct tm *tm, tm_s; time_t now; char datestring[256]; nagios_macros *mac; const char *worker_socket = NULL; int i; #ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"license", no_argument, 0, 'V'}, {"verify-config", no_argument, 0, 'v'}, {"daemon", no_argument, 0, 'd'}, {"precache-objects", no_argument, 0, 'p'}, {"use-precached-objects", no_argument, 0, 'u'}, {"enable-timing-point", no_argument, 0, 'T'}, {"worker", required_argument, 0, 'W'}, {"allow-root", no_argument, 0, 'R'}, {0, 0, 0, 0} }; #define getopt(argc, argv, o) getopt_long(argc, argv, o, long_options, &option_index) #endif /* make sure we have the correct number of command line arguments */ if (argc < 2) error = TRUE; /* get all command line arguments */ while (1) { c = getopt(argc, argv, "+hVvdspuxTW"); if (c == -1 || c == EOF) break; switch (c) { case '?': /* usage */ case 'h': display_help = TRUE; break; case 'V': /* version */ display_license = TRUE; break; case 'v': /* verify */ verify_config++; break; case 's': /* scheduling check */ printf("Warning: -s is deprecated and will be removed\n"); break; case 'd': /* daemon mode */ daemon_mode = TRUE; break; case 'p': /* precache object config */ precache_objects = TRUE; break; case 'u': /* use precached object config */ use_precached_objects = TRUE; break; case 'T': enable_timing_point = TRUE; break; case 'W': worker_socket = optarg; break; case 'R': allow_root = TRUE; break; case 'x': printf("Warning: -x is deprecated and will be removed\n"); break; default: break; } } /* Make all GLib domain messages go to the usual places. This also maps * GLib levels to an approximation of their corresponding Naemon levels * (including debug). * * Note that because of the GLib domain restriction, log messages from * other domains (such as if we did g_message(...) ourselves from inside * Naemon) do not currently go to this handler. **/ nm_g_log_handler_id = g_log_set_handler("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, nm_g_log_handler, NULL); mac = get_global_macros(); /* if we're a worker we can skip everything below */ if (worker_socket) { exit(nm_core_worker(worker_socket)); } if (daemon_mode == FALSE) { printf("\nNaemon Core " VERSION "\n"); printf("Copyright (c) 2013-present Naemon Core Development Team and Community Contributors\n"); printf("Copyright (c) 2009-2013 Nagios Core Development Team and Community Contributors\n"); printf("Copyright (c) 1999-2009 Ethan Galstad\n"); printf("License: GPL\n\n"); printf("Website: http://www.naemon.org\n"); } /* just display the license */ if (display_license == TRUE) { printf("This program is free software; you can redistribute it and/or modify\n"); printf("it under the terms of the GNU General Public License version 2 as\n"); printf("published by the Free Software Foundation.\n\n"); printf("This program is distributed in the hope that it will be useful,\n"); printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); printf("GNU General Public License for more details.\n\n"); printf("You should have received a copy of the GNU General Public License\n"); printf("along with this program; if not, write to the Free Software\n"); printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"); exit(OK); } /* make sure we got the main config file on the command line... */ if (optind >= argc) error = TRUE; /* if there are no command line options (or if we encountered an error), print usage */ if (error == TRUE || display_help == TRUE) { printf("Usage: %s [options] <main_config_file>\n", argv[0]); printf("\n"); printf("Options:\n"); printf("\n"); printf(" -v, --verify-config Verify all configuration data (-v -v for more info)\n"); printf(" -T, --enable-timing-point Enable timed commentary on initialization\n"); printf(" -x, --dont-verify-paths Deprecated (Don't check for circular object paths)\n"); printf(" -p, --precache-objects Precache object configuration\n"); printf(" -u, --use-precached-objects Use precached object config file\n"); printf(" -d, --daemon Starts Naemon in daemon mode, instead of as a foreground process\n"); printf(" -W, --worker /path/to/socket Act as a worker for an already running daemon\n"); printf(" --allow-root Let naemon run as root. THIS IS NOT RECOMMENDED AT ALL.\n"); printf("\n"); printf("Visit the Naemon website at http://www.naemon.org/ for bug fixes, new\n"); printf("releases, online documentation, FAQs and more...\n"); printf("\n"); exit(ERROR); } if (getuid() == 0) { if (allow_root == FALSE) { printf("ERROR: do not start naemon as root user.\n"); exit(EXIT_FAILURE); } else { printf("WARNING: you are running as root which is not recommended.\n"); } } /* * config file is last argument specified. * Make sure it uses an absolute path */ config_file = nspath_absolute(argv[optind], NULL); if (config_file == NULL) { printf("Error allocating memory.\n"); exit(ERROR); } config_file_dir = nspath_absolute_dirname(config_file, NULL); /* * Set the signal handler for the SIGXFSZ signal here because * we may encounter this signal before the other signal handlers * are set. */ signal(SIGXFSZ, sighandler); /* * Setup rand and srand. Don't bother with better resolution than second */ srand(time(NULL)); /* * let's go to town. We'll be noisy if we're verifying config * or running scheduling tests. */ if (verify_config || precache_objects) { reset_variables(); if (verify_config) printf("Reading configuration data...\n"); /* read our config file */ result = read_main_config_file(config_file); if (result != OK) { printf(" Error processing main config file!\n\n"); exit(EXIT_FAILURE); } if (verify_config) printf(" Read main config file okay...\n"); /* * this must come after dropping privileges, so we make * sure to test access permissions as the right user. */ if (test_configured_paths() == ERROR) { printf(" One or more path problems detected. Aborting.\n"); exit(EXIT_FAILURE); } /* read object config files */ result = read_all_object_data(config_file); if (result != OK) { printf(" Error processing object config files!\n\n"); /* if the config filename looks fishy, warn the user */ if (!strstr(config_file, "naemon.cfg")) { printf("\n***> The name of the main configuration file looks suspicious...\n"); printf("\n"); printf(" Make sure you are specifying the name of the MAIN configuration file on\n"); printf(" the command line and not the name of another configuration file. The\n"); printf(" main configuration file is typically '%s'\n", get_default_config_file()); } printf("\n***> One or more problems was encountered while processing the config files...\n"); printf("\n"); printf(" Check your configuration file(s) to ensure that they contain valid\n"); printf(" directives and data definitions. If you are upgrading from a previous\n"); printf(" version of Naemon, you should be aware that some variables/definitions\n"); printf(" may have been removed or modified in this version. Make sure to read\n"); printf(" the HTML documentation regarding the config files, as well as the\n"); printf(" 'Whats New' section to find out what has changed.\n\n"); exit(EXIT_FAILURE); } if (verify_config) { printf(" Read object config files okay...\n\n"); printf("Running pre-flight check on configuration data...\n\n"); } /* run the pre-flight check to make sure things look okay... */ result = pre_flight_check(); if (result != OK) { printf("\n***> One or more problems was encountered while running the pre-flight check...\n"); printf("\n"); printf(" Check your configuration file(s) to ensure that they contain valid\n"); printf(" directives and data definitions. If you are upgrading from a previous\n"); printf(" version of Naemon, you should be aware that some variables/definitions\n"); printf(" may have been removed or modified in this version. Make sure to read\n"); printf(" the HTML documentation regarding the config files, as well as the\n"); printf(" 'Whats New' section to find out what has changed.\n\n"); exit(EXIT_FAILURE); } if (verify_config) { printf("\nThings look okay - No serious problems were detected during the pre-flight check\n"); } if (precache_objects) { result = fcache_objects(object_precache_file); timing_point("Done precaching objects\n"); if (result == OK) { printf("Object precache file created:\n%s\n", object_precache_file); } else { printf("Failed to precache objects to '%s': %s\n", object_precache_file, strerror(errno)); } } /* clean up after ourselves */ cleanup(); /* exit */ timing_point("Exiting\n"); /* make valgrind shut up about still reachable memory */ neb_free_module_list(); free(config_file_dir); free(config_file); exit(result); } /* start to monitor things... */ /* * if we're called with a relative path we must make * it absolute so we can launch our workers. * If not, we needn't bother, as we're using execvp() */ if (strchr(argv[0], '/')) naemon_binary_path = nspath_absolute(argv[0], NULL); else naemon_binary_path = nm_strdup(argv[0]); if (!(nagios_iobs = iobroker_create())) { nm_log(NSLOG_RUNTIME_ERROR, "Error: Failed to create IO broker set: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* keep monitoring things until we get a shutdown command */ sigshutdown = sigrestart = FALSE; do { /* reset internal book-keeping (in case we're restarting) */ wproc_num_workers_spawned = wproc_num_workers_online = 0; /* reset program variables */ timing_point("Reseting variables\n"); reset_variables(); timing_point("Reset variables\n"); /* get PID */ nagios_pid = (int)getpid(); /* read in the configuration files (main and resource config files) */ timing_point("Reading main config file\n"); result = read_main_config_file(config_file); if (result != OK) { nm_log(NSLOG_CONFIG_ERROR, "Error: Failed to process config file '%s'. Aborting\n", config_file); exit(EXIT_FAILURE); } timing_point("Read main config file\n"); /* NOTE 11/06/07 EG moved to after we read config files, as user may have overridden timezone offset */ /* get program (re)start time and save as macro */ program_start = time(NULL); nm_free(mac->x[MACRO_PROCESSSTARTTIME]); nm_asprintf(&mac->x[MACRO_PROCESSSTARTTIME], "%lu", (unsigned long)program_start); if (test_path_access(naemon_binary_path, X_OK)) { nm_log(NSLOG_RUNTIME_ERROR, "Error: failed to access() %s: %s\n", naemon_binary_path, strerror(errno)); nm_log(NSLOG_RUNTIME_ERROR, "Error: Spawning workers will be impossible. Aborting.\n"); exit(EXIT_FAILURE); } if (test_configured_paths() == ERROR) { /* error has already been logged */ exit(EXIT_FAILURE); } /* enter daemon mode (unless we're restarting...) */ if (daemon_mode == TRUE && sigrestart == FALSE) { result = daemon_init(); /* we had an error daemonizing, so bail... */ if (result == ERROR) { nm_log(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, "Bailing out due to failure to daemonize. (PID=%d)", (int)getpid()); cleanup(); exit(EXIT_FAILURE); } /* get new PID */ nagios_pid = (int)getpid(); } /* this must be logged after we read config data, as user may have changed location of main log file */ nm_log(NSLOG_PROCESS_INFO, "Naemon "VERSION" starting... (PID=%d)\n", (int)getpid()); /* log the local time - may be different than clock time due to timezone offset */ now = time(NULL); tm = localtime_r(&now, &tm_s); strftime(datestring, sizeof(datestring), "%a %b %d %H:%M:%S %Z %Y", tm); nm_log(NSLOG_PROCESS_INFO, "Local time is %s", datestring); /* write log version/info */ write_log_file_info(NULL); /* open debug log now that we're the right user */ open_debug_log(); /* initialize modules */ timing_point("Initializing NEB module API\n"); neb_init_modules(); neb_init_callback_list(); timing_point("Initialized NEB module API\n"); /* handle signals (interrupts) before we do any socket I/O */ setup_sighandler(); /* * Initialize query handler and event subscription service. * This must be done before modules are initialized, so * the modules can use our in-core stuff properly */ timing_point("Initializing Query handler\n"); if (qh_init(qh_socket_path) != OK) { nm_log(NSLOG_RUNTIME_ERROR, "Error: Failed to initialize query handler. Aborting\n"); exit(EXIT_FAILURE); } timing_point("Initialized Query handler\n"); timing_point("Initializing NERD\n"); nerd_init(); timing_point("Initialized NERD\n"); /* initialize check workers */ timing_point("Spawning %u workers\n", wproc_num_workers_spawned); if (init_workers(num_check_workers) < 0) { nm_log(NSLOG_RUNTIME_ERROR, "Failed to spawn workers. Aborting\n"); exit(EXIT_FAILURE); } timing_point("Spawned %u workers\n", wproc_num_workers_spawned); timing_point("Connecting %u workers\n", wproc_num_workers_online); i = 0; while (i < 50 && wproc_num_workers_online < wproc_num_workers_spawned) { iobroker_poll(nagios_iobs, 50); i++; } timing_point("Connected %u workers\n", wproc_num_workers_online); /* read in all object config data */ if (result == OK) { timing_point("Reading all object data\n"); result = read_all_object_data(config_file); timing_point("Read all object data\n"); } /* * the queue has to be initialized before loading the neb modules * to give them the chance to register user events. * (initializing event queue requires number of objects, so do * this after parsing the objects) */ timing_point("Initializing Event queue\n"); init_event_queue(); timing_point("Initialized Event queue\n"); /* load modules */ timing_point("Loading modules\n"); if (neb_load_all_modules() != OK) { nm_log(NSLOG_CONFIG_ERROR, "Error: Module loading failed. Aborting.\n"); /* give already loaded modules a chance to deinitialize */ neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, NEBMODULE_NEB_SHUTDOWN); exit(EXIT_FAILURE); } timing_point("Loaded modules\n"); timing_point("Making first callback\n"); broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE); timing_point("Made first callback\n"); /* there was a problem reading the config files */ if (result != OK) { nm_log(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, "Bailing out due to one or more errors encountered in the configuration files. Run Naemon from the command line with the -v option to verify your config before restarting. (PID=%d)", (int)getpid()); } else { /* run the pre-flight check to make sure everything looks okay*/ timing_point("Running pre flight check\n"); if ((result = pre_flight_check()) != OK) { nm_log(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_VERIFICATION_ERROR, "Bailing out due to errors encountered while running the pre-flight check. Run Naemon from the command line with the -v option to verify your config before restarting. (PID=%d)\n", (int)getpid()); } timing_point("Ran pre flight check\n"); } /* an error occurred that prevented us from (re)starting */ if (result != OK) { /* if we were restarting, we need to cleanup from the previous run */ if (sigrestart == TRUE) { /* clean up the status data */ cleanup_status_data(TRUE); } broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL); cleanup(); exit(ERROR); } /* write the objects.cache file */ timing_point("Caching objects\n"); fcache_objects(object_cache_file); timing_point("Cached objects\n"); broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE); timing_point("Initializing status data\n"); initialize_status_data(config_file); timing_point("Initialized status data\n"); /* initialize scheduled downtime data */ timing_point("Initializing downtime data\n"); initialize_downtime_data(); timing_point("Initialized downtime data\n"); /* read initial service and host state information */ timing_point("Initializing retention data\n"); initialize_retention_data(); timing_point("Initialized retention data\n"); timing_point("Reading initial state information\n"); read_initial_state_information(); timing_point("Read initial state information\n"); /* initialize comment data */ timing_point("Initializing comment data\n"); initialize_comment_data(); timing_point("Initialized comment data\n"); /* initialize performance data */ timing_point("Initializing performance data\n"); initialize_performance_data(config_file); timing_point("Initialized performance data\n"); /* initialize the check execution subsystem */ timing_point("Initializing check execution scheduling\n"); checks_init(); timing_point("Initialized check execution scheduling\n"); /* initialize check statistics */ timing_point("Initializing check stats\n"); init_check_stats(); timing_point("Initialized check stats\n"); /* update all status data (with retained information) */ timing_point("Updating status data\n"); update_all_status_data(); timing_point("Updated status data\n"); /* log initial host and service state */ timing_point("Logging initial states\n"); log_host_states(INITIAL_STATES, NULL); log_service_states(INITIAL_STATES, NULL); timing_point("Logged initial states\n"); registered_commands_init(200); register_core_commands(); /* fire up command file worker */ timing_point("Launching command file worker\n"); launch_command_file_worker(); timing_point("Launched command file worker\n"); broker_program_state(NEBTYPE_PROCESS_EVENTLOOPSTART, NEBFLAG_NONE, NEBATTR_NONE); /* get event start time and save as macro */ event_start = time(NULL); nm_free(mac->x[MACRO_EVENTSTARTTIME]); nm_asprintf(&mac->x[MACRO_EVENTSTARTTIME], "%lu", (unsigned long)event_start); /* let the parent know we're good to go and that it can let go */ if (daemon_mode == TRUE && sigrestart == FALSE) { if ((result = signal_parent(OK)) != OK) { broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL); cleanup(); exit(ERROR); } } timing_point("Entering event execution loop\n"); /***** start monitoring all services *****/ /* (doesn't return until a restart or shutdown signal is encountered) */ sigshutdown = sigrestart = FALSE; event_execution_loop(); /* * immediately deinitialize the query handler so it * can remove modules that have stashed data with it */ qh_deinit(qh_socket_path); /* * handle any incoming signals */ signal_react(); broker_program_state(NEBTYPE_PROCESS_EVENTLOOPEND, NEBFLAG_NONE, NEBATTR_NONE); if (sigshutdown == TRUE) broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_USER_INITIATED, NEBATTR_SHUTDOWN_NORMAL); else if (sigrestart == TRUE) broker_program_state(NEBTYPE_PROCESS_RESTART, NEBFLAG_USER_INITIATED, NEBATTR_RESTART_NORMAL); disconnect_command_file_worker(); /* save service and host state information */ save_state_information(FALSE); cleanup_retention_data(); /* clean up performance data */ cleanup_performance_data(); /* clean up the scheduled downtime data */ cleanup_downtime_data(); /* clean up the status data unless we're restarting */ cleanup_status_data(!sigrestart); registered_commands_deinit(); free_worker_memory(WPROC_FORCE); /* shutdown stuff... */ if (sigshutdown == TRUE) { iobroker_destroy(nagios_iobs, IOBROKER_CLOSE_SOCKETS); nagios_iobs = NULL; /* log a shutdown message */ nm_log(NSLOG_PROCESS_INFO, "Successfully shutdown... (PID=%d)\n", (int)getpid()); } /* clean up after ourselves */ cleanup(); /* close debug log */ close_debug_log(); } while (sigrestart == TRUE && sigshutdown == FALSE); shutdown_command_file_worker(); if (daemon_mode == TRUE) unlink(lock_file); /* free misc memory */ nm_free(lock_file); nm_free(config_file); nm_free(config_file_dir); nm_free(naemon_binary_path); return OK; }
void test_host_commands(void) { char *host_name = "host1"; host *target_host = NULL; int pre = 0, prev_comment_id = next_comment_id; unsigned int prev_downtime_id; time_t check_time =0; char *cmdstr = NULL; target_host = find_host(host_name); target_host->obsess = FALSE; pre = number_of_host_comments(host_name); ok(CMD_ERROR_OK == process_external_command2(CMD_ADD_HOST_COMMENT, check_time, "host1;0;myself;my comment"), "process_external_command2: ADD_HOST_COMMENT"); ok(pre+1 == number_of_host_comments(host_name), "ADD_HOST_COMMENT (through process_external_command2) adds a host comment"); ++pre; ok(CMD_ERROR_OK == process_external_command1("[1234567890] ADD_HOST_COMMENT;host1;0;myself;my comment"), "core command: ADD_HOST_COMMENT"); ok(pre+1 == number_of_host_comments(host_name), "ADD_HOST_COMMENT adds a host comment"); nm_asprintf(&cmdstr, "[1234567890] DEL_HOST_COMMENT;%i", prev_comment_id); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: DEL_HOST_COMMENT"); free(cmdstr); ok(pre == number_of_host_comments(host_name), "DEL_HOST_COMMENT deletes a host comment"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DELAY_HOST_NOTIFICATION;host1;1927587190"), "core command: DELAY_HOST_NOTIFICATION"); ok(1927587190 == target_host->next_notification, "DELAY_HOST_NOTIFICATION delays host notifications"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_SVC_CHECKS;host1"), "core command: DISABLE_HOST_SVC_CHECKS"); ok(!target_host->services->service_ptr->checks_enabled, "DISABLE_HOST_SVC_CHECKS disables active checks for services on a host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_SVC_CHECKS;host1"), "core command: ENABLE_HOST_SVC_CHECKS"); ok(target_host->services->service_ptr->checks_enabled, "ENABLE_HOST_SVC_CHECKS enables active checks for services on a host"); check_time = target_host->services->service_ptr->next_check - 20; nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_HOST_SVC_CHECKS;host1;%llu", (long long unsigned int)check_time); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_HOST_SVC_CHECKS"); ok(check_time == target_host->services->service_ptr->next_check, "SCHEDULE_HOST_SVC_CHECKS schedules host service checks"); free(cmdstr); assert(CMD_ERROR_OK == process_external_command1("[1234567890] ADD_HOST_COMMENT;host1;0;myself;comment 1")); assert(CMD_ERROR_OK == process_external_command1("[1234567890] ADD_HOST_COMMENT;host1;1;myself;comment 2")); assert(CMD_ERROR_OK == process_external_command1("[1234567890] ADD_HOST_COMMENT;host1;0;myself;comment 3")); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DEL_ALL_HOST_COMMENTS;host1"), "core command: DEL_ALL_HOST_COMMENTS"); ok(0 == number_of_host_comments(host_name), "DEL_ALL_HOST_COMMENTS deletes all host comments"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_NOTIFICATIONS;host1"), "core command: DISABLE_HOST_NOTIFICATIONS"); ok(!target_host->notifications_enabled, "DISABLE_HOST_NOTIFICATIONS disables host notifications"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_NOTIFICATIONS;host1"), "core command: ENABLE_HOST_NOTIFICATIONS"); ok(target_host->notifications_enabled, "ENABLE_HOST_NOTIFICATIONS enables host notifications"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST;host1"), "core command: DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST"); ok(!((find_host("childofhost1"))->notifications_enabled), "DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST disables notifications beyond host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST;host1"), "core command: ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST"); ok(((find_host("childofhost1"))->notifications_enabled), "ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST enables notifications beyond host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_SVC_NOTIFICATIONS;host1"), "core command: DISABLE_HOST_SVC_NOTIFICATIONS"); ok(!(target_host->services->service_ptr->notifications_enabled), "DISABLE_HOST_SVC_NOTIFICATIONS disables notifications for services on a host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_SVC_NOTIFICATIONS;host1"), "core command: ENABLE_HOST_SVC_NOTIFICATIONS"); ok(target_host->services->service_ptr->notifications_enabled, "ENABLE_HOST_SVC_NOTIFICATIONS enables notifications for services on a host"); target_host->current_state = STATE_DOWN; ok(CMD_ERROR_OK == process_external_command1("[1234567890] ACKNOWLEDGE_HOST_PROBLEM;host1;2;0;0;myself;my ack comment"), "core command: ACKNOWLEDGE_HOST_PROBLEM"); ok(target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM acknowledges a host problem"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] REMOVE_HOST_ACKNOWLEDGEMENT;host1"), "core command: REMOVE_HOST_ACKNOWLEDGEMENT"); ok(!target_host->problem_has_been_acknowledged, "REMOVE_HOST_ACKNOWLEDGEMENT removes a host acknowledgement"); target_host->current_state = STATE_UP; ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_EVENT_HANDLER;host1"), "core command: DISABLE_HOST_EVENT_HANDLER"); ok(!target_host->event_handler_enabled, "DISABLE_HOST_EVENT_HANDLER disables event handler for a host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_EVENT_HANDLER;host1"), "core command: ENABLE_HOST_EVENT_HANDLER"); ok(target_host->event_handler_enabled, "ENABLE_HOST_EVENT_HANDLER enables event handler for a host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_CHECK;host1"), "core command: DISABLE_HOST_CHECK"); ok(!target_host->checks_enabled, "DISABLE_HOST_CHECK disables active host checks"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_CHECK;host1"), "core command: ENABLE_HOST_CHECK"); ok(target_host->checks_enabled, "ENABLE_HOST_CHECK enables active host checks"); check_time = target_host->services->service_ptr->next_check + 2000; nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_FORCED_HOST_SVC_CHECKS;host1;%llu", (unsigned long long int)check_time); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_FORCED_HOST_SVC_CHECKS"); ok(check_time == target_host->services->service_ptr->next_check, "SCHEDULE_FORCED_HOST_SVC_CHECKS schedules forced checks for services on a host"); free(cmdstr); prev_downtime_id = next_downtime_id; nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_HOST_DOWNTIME;host1;%llu;%llu;1;0;0;myself;my downtime comment", (unsigned long long int)time(NULL), (unsigned long long int)time(NULL) + 1500); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_HOST_DOWNTIME"); ok(prev_downtime_id != next_downtime_id, "SCHEDULE_HOST_DOWNTIME schedules one new downtime"); ok(NULL != find_host_downtime(prev_downtime_id), "SCHEDULE_HOST_DOWNTIME schedules downtime for a host"); free(cmdstr); nm_asprintf(&cmdstr, "[1234567890] DEL_HOST_DOWNTIME;%i", prev_downtime_id); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: DEL_HOST_DOWNTIME"); ok(!find_host_downtime(prev_downtime_id), "DEL_HOST_DOWNTIME deletes a scheduled host downtime"); free(cmdstr); ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_FLAP_DETECTION;host1"), "core command: DISABLE_HOST_FLAP_DETECTION"); ok(!target_host->flap_detection_enabled, "DISABLE_HOST_FLAP_DETECTION disables host flap detection"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] ENABLE_HOST_FLAP_DETECTION;host1"), "core command: ENABLE_HOST_FLAP_DETECTION"); ok(target_host->flap_detection_enabled, "ENABLE_HOST_FLAP_DETECTION enables host flap detection"); assert(NULL == find_service_downtime(0)); nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_HOST_SVC_DOWNTIME;host1;%llu;%llu;1;0;0;myself;my downtime comment", (unsigned long long int)time(NULL), (unsigned long long int)time(NULL) + 1500); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_HOST_SVC_DOWNTIME"); strcmp(host_name, find_service_downtime(0)->host_name); ok(0 == 0, "SCHEDULE_HOST_SVC_DOWNTIME schedules downtime for services on a host"); free(cmdstr); ok(CMD_ERROR_OK == process_external_command1("[1234567890] PROCESS_HOST_CHECK_RESULT;host1;1;some plugin output"), "core command: PROCESS_HOST_CHECK_RESULT"); ok(target_host->current_state == STATE_DOWN, "PROCESS_HOST_CHECK_RESULT processes host check results"); check_time = target_host->next_check - 20; nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_HOST_CHECK;host1;%llu", (unsigned long long int)check_time); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_HOST_CHECK"); ok(check_time == target_host->next_check, "SCHEDULE_HOST_CHECK schedules a host check"); free(cmdstr); nm_asprintf(&cmdstr, "[1234567890] SCHEDULE_HOST_CHECK;host1;%llu", (unsigned long long int)check_time); ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: SCHEDULE_FORCED_HOST_CHECK"); ok(check_time == target_host->next_check, "SCHEDULE_FORCED_HOST_CHECK schedules a host check"); free(cmdstr); assert(!(target_host->obsess)); ok(CMD_ERROR_OK == process_external_command1("[1234567890] START_OBSESSING_OVER_HOST;host1"), "core command: START_OBSESSING_OVER_HOST"); ok(target_host->obsess, "START_OBSESSING_OVER_HOST enables OCHP for host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] STOP_OBSESSING_OVER_HOST;host1"), "core command: STOP_OBSESSING_OVER_HOST"); ok(!target_host->obsess, "STOP_OBSESSING_OVER_HOST disables OCHP for host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] CHANGE_NORMAL_HOST_CHECK_INTERVAL;host1;42"), "core command: CHANGE_NORMAL_HOST_CHECK_INTERVAL"); ok(42 == target_host->check_interval, "CHANGE_NORMAL_HOST_CHECK_INTERVAL changes the host check inteval for host"); ok(CMD_ERROR_OK == process_external_command1("[1234567890] CHANGE_MAX_HOST_CHECK_ATTEMPTS;host1;9"), "core command: CHANGE_MAX_HOST_CHECK_ATTEMPTS"); ok(9 == target_host->max_attempts, "CHANGE_MAX_HOST_CHECK_ATTEMPTS changes the maximum number of check attempts for host"); }
/* write all status data to file */ int xsddefault_save_status_data(void) { char *tmp_log = NULL; customvariablesmember *temp_customvariablesmember = NULL; host *temp_host = NULL; service *temp_service = NULL; contact *temp_contact = NULL; comment *temp_comment = NULL; scheduled_downtime *temp_downtime = NULL; time_t current_time; int fd = 0; FILE *fp = NULL; int result = OK; /* users may not want us to write status data */ if (!status_file || !strcmp(status_file, "/dev/null")) return OK; nm_asprintf(&tmp_log, "%sXXXXXX", temp_file); if (tmp_log == NULL) return ERROR; log_debug_info(DEBUGL_STATUSDATA, 2, "Writing status data to temp file '%s'\n", tmp_log); if ((fd = mkstemp(tmp_log)) == -1) { /* log an error */ nm_log(NSLOG_RUNTIME_ERROR, "Error: Unable to create temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno)); nm_free(tmp_log); return ERROR; } fp = (FILE *)fdopen(fd, "w"); if (fp == NULL) { close(fd); unlink(tmp_log); /* log an error */ nm_log(NSLOG_RUNTIME_ERROR, "Error: Unable to open temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno)); nm_free(tmp_log); return ERROR; } /* generate check statistics */ generate_check_stats(); /* write version info to status file */ fprintf(fp, "########################################\n"); fprintf(fp, "# NAGIOS STATUS FILE\n"); fprintf(fp, "#\n"); fprintf(fp, "# THIS FILE IS AUTOMATICALLY GENERATED\n"); fprintf(fp, "# BY NAGIOS. DO NOT MODIFY THIS FILE!\n"); fprintf(fp, "########################################\n\n"); time(¤t_time); /* write file info */ fprintf(fp, "info {\n"); fprintf(fp, "\tcreated=%lu\n", current_time); fprintf(fp, "\tversion=" VERSION "\n"); fprintf(fp, "\t}\n\n"); /* save program status data */ fprintf(fp, "programstatus {\n"); fprintf(fp, "\tmodified_host_attributes=%lu\n", modified_host_process_attributes); fprintf(fp, "\tmodified_service_attributes=%lu\n", modified_service_process_attributes); fprintf(fp, "\tnagios_pid=%d\n", nagios_pid); fprintf(fp, "\tdaemon_mode=%d\n", daemon_mode); fprintf(fp, "\tprogram_start=%lu\n", program_start); fprintf(fp, "\tlast_log_rotation=%lu\n", last_log_rotation); fprintf(fp, "\tenable_notifications=%d\n", enable_notifications); fprintf(fp, "\tactive_service_checks_enabled=%d\n", execute_service_checks); fprintf(fp, "\tpassive_service_checks_enabled=%d\n", accept_passive_service_checks); fprintf(fp, "\tactive_host_checks_enabled=%d\n", execute_host_checks); fprintf(fp, "\tpassive_host_checks_enabled=%d\n", accept_passive_host_checks); fprintf(fp, "\tenable_event_handlers=%d\n", enable_event_handlers); fprintf(fp, "\tobsess_over_services=%d\n", obsess_over_services); fprintf(fp, "\tobsess_over_hosts=%d\n", obsess_over_hosts); fprintf(fp, "\tcheck_service_freshness=%d\n", check_service_freshness); fprintf(fp, "\tcheck_host_freshness=%d\n", check_host_freshness); fprintf(fp, "\tenable_flap_detection=%d\n", enable_flap_detection); fprintf(fp, "\tprocess_performance_data=%d\n", process_performance_data); fprintf(fp, "\tglobal_host_event_handler=%s\n", (global_host_event_handler == NULL) ? "" : global_host_event_handler); fprintf(fp, "\tglobal_service_event_handler=%s\n", (global_service_event_handler == NULL) ? "" : global_service_event_handler); fprintf(fp, "\tnext_comment_id=%lu\n", next_comment_id); fprintf(fp, "\tnext_downtime_id=%lu\n", next_downtime_id); fprintf(fp, "\tnext_event_id=%lu\n", next_event_id); fprintf(fp, "\tnext_problem_id=%lu\n", next_problem_id); fprintf(fp, "\tnext_notification_id=%lu\n", next_notification_id); fprintf(fp, "\tactive_scheduled_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_SCHEDULED_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tactive_ondemand_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_ONDEMAND_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tpassive_host_check_stats=%d,%d,%d\n", check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[0], check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[1], check_statistics[PASSIVE_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tactive_scheduled_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tactive_ondemand_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tpassive_service_check_stats=%d,%d,%d\n", check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[PASSIVE_SERVICE_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tcached_host_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_CACHED_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tcached_service_check_stats=%d,%d,%d\n", check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[0], check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[1], check_statistics[ACTIVE_CACHED_SERVICE_CHECK_STATS].minute_stats[2]); fprintf(fp, "\texternal_command_stats=%d,%d,%d\n", check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[0], check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[1], check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[2]); fprintf(fp, "\tparallel_host_check_stats=%d,%d,%d\n", check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[0], check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[1], check_statistics[PARALLEL_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\tserial_host_check_stats=%d,%d,%d\n", check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[0], check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[1], check_statistics[SERIAL_HOST_CHECK_STATS].minute_stats[2]); fprintf(fp, "\t}\n\n"); /* save host status data */ for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { fprintf(fp, "hoststatus {\n"); fprintf(fp, "\thost_name=%s\n", temp_host->name); fprintf(fp, "\tmodified_attributes=%lu\n", temp_host->modified_attributes); fprintf(fp, "\tcheck_command=%s\n", (temp_host->check_command == NULL) ? "" : temp_host->check_command); fprintf(fp, "\tcheck_period=%s\n", (temp_host->check_period == NULL) ? "" : temp_host->check_period); fprintf(fp, "\tnotification_period=%s\n", (temp_host->notification_period == NULL) ? "" : temp_host->notification_period); fprintf(fp, "\tcheck_interval=%f\n", temp_host->check_interval); fprintf(fp, "\tretry_interval=%f\n", temp_host->retry_interval); fprintf(fp, "\tevent_handler=%s\n", (temp_host->event_handler == NULL) ? "" : temp_host->event_handler); fprintf(fp, "\thas_been_checked=%d\n", temp_host->has_been_checked); fprintf(fp, "\tcheck_execution_time=%.3f\n", temp_host->execution_time); fprintf(fp, "\tcheck_latency=%.3f\n", temp_host->latency); fprintf(fp, "\tcheck_type=%d\n", temp_host->check_type); fprintf(fp, "\tcurrent_state=%d\n", temp_host->current_state); fprintf(fp, "\tlast_hard_state=%d\n", temp_host->last_hard_state); fprintf(fp, "\tlast_event_id=%lu\n", temp_host->last_event_id); fprintf(fp, "\tcurrent_event_id=%lu\n", temp_host->current_event_id); fprintf(fp, "\tcurrent_problem_id=%lu\n", temp_host->current_problem_id); fprintf(fp, "\tlast_problem_id=%lu\n", temp_host->last_problem_id); fprintf(fp, "\tplugin_output=%s\n", (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output); fprintf(fp, "\tlong_plugin_output=%s\n", (temp_host->long_plugin_output == NULL) ? "" : temp_host->long_plugin_output); fprintf(fp, "\tperformance_data=%s\n", (temp_host->perf_data == NULL) ? "" : temp_host->perf_data); fprintf(fp, "\tlast_check=%lu\n", temp_host->last_check); fprintf(fp, "\tnext_check=%lu\n", temp_host->next_check); fprintf(fp, "\tcheck_options=%d\n", temp_host->check_options); fprintf(fp, "\tcurrent_attempt=%d\n", temp_host->current_attempt); fprintf(fp, "\tmax_attempts=%d\n", temp_host->max_attempts); fprintf(fp, "\tstate_type=%d\n", temp_host->state_type); fprintf(fp, "\tlast_state_change=%lu\n", temp_host->last_state_change); fprintf(fp, "\tlast_hard_state_change=%lu\n", temp_host->last_hard_state_change); fprintf(fp, "\tlast_time_up=%lu\n", temp_host->last_time_up); fprintf(fp, "\tlast_time_down=%lu\n", temp_host->last_time_down); fprintf(fp, "\tlast_time_unreachable=%lu\n", temp_host->last_time_unreachable); fprintf(fp, "\tlast_notification=%lu\n", temp_host->last_notification); fprintf(fp, "\tnext_notification=%lu\n", temp_host->next_notification); fprintf(fp, "\tno_more_notifications=%d\n", temp_host->no_more_notifications); fprintf(fp, "\tcurrent_notification_number=%d\n", temp_host->current_notification_number); fprintf(fp, "\tcurrent_notification_id=%lu\n", temp_host->current_notification_id); fprintf(fp, "\tnotifications_enabled=%d\n", temp_host->notifications_enabled); fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged); fprintf(fp, "\tacknowledgement_type=%d\n", temp_host->acknowledgement_type); fprintf(fp, "\tactive_checks_enabled=%d\n", temp_host->checks_enabled); fprintf(fp, "\tpassive_checks_enabled=%d\n", temp_host->accept_passive_checks); fprintf(fp, "\tevent_handler_enabled=%d\n", temp_host->event_handler_enabled); fprintf(fp, "\tflap_detection_enabled=%d\n", temp_host->flap_detection_enabled); fprintf(fp, "\tprocess_performance_data=%d\n", temp_host->process_performance_data); fprintf(fp, "\tobsess=%d\n", temp_host->obsess); fprintf(fp, "\tlast_update=%lu\n", current_time); fprintf(fp, "\tis_flapping=%d\n", temp_host->is_flapping); fprintf(fp, "\tpercent_state_change=%.2f\n", temp_host->percent_state_change); fprintf(fp, "\tscheduled_downtime_depth=%d\n", temp_host->scheduled_downtime_depth); /* custom variables */ for (temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { if (temp_customvariablesmember->variable_name) fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value); } fprintf(fp, "\t}\n\n"); } /* save service status data */ for (temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { fprintf(fp, "servicestatus {\n"); fprintf(fp, "\thost_name=%s\n", temp_service->host_name); fprintf(fp, "\tservice_description=%s\n", temp_service->description); fprintf(fp, "\tmodified_attributes=%lu\n", temp_service->modified_attributes); fprintf(fp, "\tcheck_command=%s\n", (temp_service->check_command == NULL) ? "" : temp_service->check_command); fprintf(fp, "\tcheck_period=%s\n", (temp_service->check_period == NULL) ? "" : temp_service->check_period); fprintf(fp, "\tnotification_period=%s\n", (temp_service->notification_period == NULL) ? "" : temp_service->notification_period); fprintf(fp, "\tcheck_interval=%f\n", temp_service->check_interval); fprintf(fp, "\tretry_interval=%f\n", temp_service->retry_interval); fprintf(fp, "\tevent_handler=%s\n", (temp_service->event_handler == NULL) ? "" : temp_service->event_handler); fprintf(fp, "\thas_been_checked=%d\n", temp_service->has_been_checked); fprintf(fp, "\tcheck_execution_time=%.3f\n", temp_service->execution_time); fprintf(fp, "\tcheck_latency=%.3f\n", temp_service->latency); fprintf(fp, "\tcheck_type=%d\n", temp_service->check_type); fprintf(fp, "\tcurrent_state=%d\n", temp_service->current_state); fprintf(fp, "\tlast_hard_state=%d\n", temp_service->last_hard_state); fprintf(fp, "\tlast_event_id=%lu\n", temp_service->last_event_id); fprintf(fp, "\tcurrent_event_id=%lu\n", temp_service->current_event_id); fprintf(fp, "\tcurrent_problem_id=%lu\n", temp_service->current_problem_id); fprintf(fp, "\tlast_problem_id=%lu\n", temp_service->last_problem_id); fprintf(fp, "\tcurrent_attempt=%d\n", temp_service->current_attempt); fprintf(fp, "\tmax_attempts=%d\n", temp_service->max_attempts); fprintf(fp, "\tstate_type=%d\n", temp_service->state_type); fprintf(fp, "\tlast_state_change=%lu\n", temp_service->last_state_change); fprintf(fp, "\tlast_hard_state_change=%lu\n", temp_service->last_hard_state_change); fprintf(fp, "\tlast_time_ok=%lu\n", temp_service->last_time_ok); fprintf(fp, "\tlast_time_warning=%lu\n", temp_service->last_time_warning); fprintf(fp, "\tlast_time_unknown=%lu\n", temp_service->last_time_unknown); fprintf(fp, "\tlast_time_critical=%lu\n", temp_service->last_time_critical); fprintf(fp, "\tplugin_output=%s\n", (temp_service->plugin_output == NULL) ? "" : temp_service->plugin_output); fprintf(fp, "\tlong_plugin_output=%s\n", (temp_service->long_plugin_output == NULL) ? "" : temp_service->long_plugin_output); fprintf(fp, "\tperformance_data=%s\n", (temp_service->perf_data == NULL) ? "" : temp_service->perf_data); fprintf(fp, "\tlast_check=%lu\n", temp_service->last_check); fprintf(fp, "\tnext_check=%lu\n", temp_service->next_check); fprintf(fp, "\tcheck_options=%d\n", temp_service->check_options); fprintf(fp, "\tcurrent_notification_number=%d\n", temp_service->current_notification_number); fprintf(fp, "\tcurrent_notification_id=%lu\n", temp_service->current_notification_id); fprintf(fp, "\tlast_notification=%lu\n", temp_service->last_notification); fprintf(fp, "\tnext_notification=%lu\n", temp_service->next_notification); fprintf(fp, "\tno_more_notifications=%d\n", temp_service->no_more_notifications); fprintf(fp, "\tnotifications_enabled=%d\n", temp_service->notifications_enabled); fprintf(fp, "\tactive_checks_enabled=%d\n", temp_service->checks_enabled); fprintf(fp, "\tpassive_checks_enabled=%d\n", temp_service->accept_passive_checks); fprintf(fp, "\tevent_handler_enabled=%d\n", temp_service->event_handler_enabled); fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged); fprintf(fp, "\tacknowledgement_type=%d\n", temp_service->acknowledgement_type); fprintf(fp, "\tflap_detection_enabled=%d\n", temp_service->flap_detection_enabled); fprintf(fp, "\tprocess_performance_data=%d\n", temp_service->process_performance_data); fprintf(fp, "\tobsess=%d\n", temp_service->obsess); fprintf(fp, "\tlast_update=%lu\n", current_time); fprintf(fp, "\tis_flapping=%d\n", temp_service->is_flapping); fprintf(fp, "\tpercent_state_change=%.2f\n", temp_service->percent_state_change); fprintf(fp, "\tscheduled_downtime_depth=%d\n", temp_service->scheduled_downtime_depth); /* custom variables */ for (temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { if (temp_customvariablesmember->variable_name) fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value); } fprintf(fp, "\t}\n\n"); } /* save contact status data */ for (temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) { fprintf(fp, "contactstatus {\n"); fprintf(fp, "\tcontact_name=%s\n", temp_contact->name); fprintf(fp, "\tmodified_attributes=%lu\n", temp_contact->modified_attributes); fprintf(fp, "\tmodified_host_attributes=%lu\n", temp_contact->modified_host_attributes); fprintf(fp, "\tmodified_service_attributes=%lu\n", temp_contact->modified_service_attributes); fprintf(fp, "\thost_notification_period=%s\n", (temp_contact->host_notification_period == NULL) ? "" : temp_contact->host_notification_period); fprintf(fp, "\tservice_notification_period=%s\n", (temp_contact->service_notification_period == NULL) ? "" : temp_contact->service_notification_period); fprintf(fp, "\tlast_host_notification=%lu\n", temp_contact->last_host_notification); fprintf(fp, "\tlast_service_notification=%lu\n", temp_contact->last_service_notification); fprintf(fp, "\thost_notifications_enabled=%d\n", temp_contact->host_notifications_enabled); fprintf(fp, "\tservice_notifications_enabled=%d\n", temp_contact->service_notifications_enabled); /* custom variables */ for (temp_customvariablesmember = temp_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { if (temp_customvariablesmember->variable_name) fprintf(fp, "\t_%s=%d;%s\n", temp_customvariablesmember->variable_name, temp_customvariablesmember->has_been_modified, (temp_customvariablesmember->variable_value == NULL) ? "" : temp_customvariablesmember->variable_value); } fprintf(fp, "\t}\n\n"); } /* save all comments */ for (temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) { if (temp_comment->comment_type == HOST_COMMENT) fprintf(fp, "hostcomment {\n"); else fprintf(fp, "servicecomment {\n"); fprintf(fp, "\thost_name=%s\n", temp_comment->host_name); if (temp_comment->comment_type == SERVICE_COMMENT) fprintf(fp, "\tservice_description=%s\n", temp_comment->service_description); fprintf(fp, "\tentry_type=%d\n", temp_comment->entry_type); fprintf(fp, "\tcomment_id=%lu\n", temp_comment->comment_id); fprintf(fp, "\tsource=%d\n", temp_comment->source); fprintf(fp, "\tpersistent=%d\n", temp_comment->persistent); fprintf(fp, "\tentry_time=%lu\n", temp_comment->entry_time); fprintf(fp, "\texpires=%d\n", temp_comment->expires); fprintf(fp, "\texpire_time=%lu\n", temp_comment->expire_time); fprintf(fp, "\tauthor=%s\n", temp_comment->author); fprintf(fp, "\tcomment_data=%s\n", temp_comment->comment_data); fprintf(fp, "\t}\n\n"); } /* save all downtime */ for (temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { if (temp_downtime->type == HOST_DOWNTIME) fprintf(fp, "hostdowntime {\n"); else fprintf(fp, "servicedowntime {\n"); fprintf(fp, "\thost_name=%s\n", temp_downtime->host_name); if (temp_downtime->type == SERVICE_DOWNTIME) fprintf(fp, "\tservice_description=%s\n", temp_downtime->service_description); fprintf(fp, "\tdowntime_id=%lu\n", temp_downtime->downtime_id); fprintf(fp, "\tcomment_id=%lu\n", temp_downtime->comment_id); fprintf(fp, "\tentry_time=%lu\n", temp_downtime->entry_time); fprintf(fp, "\tstart_time=%lu\n", temp_downtime->start_time); fprintf(fp, "\tflex_downtime_start=%lu\n", temp_downtime->flex_downtime_start); fprintf(fp, "\tend_time=%lu\n", temp_downtime->end_time); fprintf(fp, "\ttriggered_by=%lu\n", temp_downtime->triggered_by); fprintf(fp, "\tfixed=%d\n", temp_downtime->fixed); fprintf(fp, "\tduration=%lu\n", temp_downtime->duration); fprintf(fp, "\tis_in_effect=%d\n", temp_downtime->is_in_effect); fprintf(fp, "\tstart_notification_sent=%d\n", temp_downtime->start_notification_sent); fprintf(fp, "\tauthor=%s\n", temp_downtime->author); fprintf(fp, "\tcomment=%s\n", temp_downtime->comment); fprintf(fp, "\t}\n\n"); } /* reset file permissions */ fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); /* flush the file to disk */ fflush(fp); /* fsync the file so that it is completely written out before moving it */ fsync(fd); /* close the temp file */ result = fclose(fp); /* save/close was successful */ if (result == 0) { result = OK; /* move the temp file to the status log (overwrite the old status log) */ if (my_rename(tmp_log, status_file)) { unlink(tmp_log); nm_log(NSLOG_RUNTIME_ERROR, "Error: Unable to update status data file '%s': %s", status_file, strerror(errno)); result = ERROR; } } /* a problem occurred saving the file */ else { result = ERROR; /* remove temp file and log an error */ unlink(tmp_log); nm_log(NSLOG_RUNTIME_ERROR, "Error: Unable to save status file: %s", strerror(errno)); } nm_free(tmp_log); return result; }